You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Canvas绘制列表中相同GameItem时部分不显示问题求助

问题:同类型GameItem仅显示一个,其余未绘制
  • 现象:战斗结果界面绘制奖励物品时,若列表存在同类型GameItem,Canvas仅绘制其中一个,其余被跳过;库存界面无此问题。
  • 补充:有19秒问题演示视频。

BattleResultDialog代码

Paint fadePaint;
int scrollMarginTop;
int scrollPaddingTop;
int frameCount;

int questTextSize, completeTextSize;

boolean battleWin;

ArrayList<GameItem> rewards;

public BattleResultDialog(boolean battleComplete, Enemy enemyObject) {
    super(540,1080,1080,2160);
    rewards = enemyObject.rewardsList;
    scrollMarginTop = scaling.DrawY(100);
    scrollPaddingTop = scaling.DrawY(100);

    fadePaint = new Paint();
    fadePaint.setARGB(0,0,0,0);

    questTextSize = 0;

    if(MainActivity.playerData.hp > 0 && battleComplete){
        battleWin = true;
        int count = 0;

        for (GameItem g: rewards) {
                g.updateXY(((160*count)),1080);
                Log.d("ITEMTYPE:",g.itemType+":: X:"+g.x+": y:"+g.y);
            count++;
        }
        SocketManager.myConsumableList.addAll(rewards);
        MainActivity.playerData.xp += SocketManager.Enemylist.get(MainActivity.playerData.currentEnemyIndex).xpReward;
        MainActivity.playerData.currentEnemyIndex = 0;
        mapSelectIcon = new MapSelectIcon(0,0,0,0,false,1,MainActivity.playerData.currentEnemyIndex);
        SocketManager.Enemylist.get(MainActivity.playerData.currentEnemyIndex).isDead = true;
        SocketManager.Enemylist.remove(enemyObject);

        for (Enemy e:SocketManager.Enemylist) {
            e.ResetMapIcons();
        }

        MainActivity.playerData.TallyLVL();
    }
}

public void update() {
    super.update();
    frameCount++;

    if(MainActivity.playerData.justUpgradedLVL){
        if(frameCount >30){
            MainActivity.playerData.justUpgradedLVL = false;
        }
    }

    if(battleWin){
        for (GameItem g:rewards) {
            g.update();
        }
    }

    if(frameCount >30 && frameCount < 60){
        questTextSize = questTextSize + 4;
    }
    if(frameCount >45 && frameCount < 75){
        completeTextSize = completeTextSize + 4;
    }

    if(fadePaint.getAlpha() <= 245){
        fadePaint.setAlpha(fadePaint.getAlpha()+9);
    }else{
        fadePaint.setAlpha(255);
    }
}

public void draw(Canvas canvas) {
    canvas.drawBitmap(Globals.SplashBG,0,0,fadePaint); //zindex 0

    canvas.drawText("BATTLE", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(100) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.black, questTextSize, 0, 6, R.font.grobold,255));
    canvas.drawText("BATTLE", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(100) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.white, questTextSize, 0, 0, R.font.grobold,255));
    canvas.drawText("RESULTS", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(300) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.black, completeTextSize, 0, 6, R.font.grobold,255));
    canvas.drawText("RESULTS", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(300) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.white, completeTextSize, 0, 0, R.font.grobold,255));

    if(battleWin){
        canvas.drawText("YALL WON", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(700) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.black, completeTextSize, 0, 6, R.font.grobold,255));
        canvas.drawText("YALL WON", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(700) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.white, completeTextSize, 0, 0, R.font.grobold,255));

        //Show the reward Items
        canvas.drawText("numRewards"+rewards.size(), super.rect.centerX(), super.rect.top + scaling.DrawY(1400), TextGen.getFont(android.R.color.black, 40, 0, 6, R.font.grobold,255));
        canvas.drawText("numRewards"+rewards.size(), super.rect.centerX(), super.rect.top + scaling.DrawY(1400), TextGen.getFont(android.R.color.white, 40, 0, 0, R.font.grobold,255));

        for (GameItem g:rewards) {
            g.draw(canvas);
        }
    }else{
        canvas.drawText("YALL DIED", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(700) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.black, completeTextSize, 0, 6, R.font.grobold,255));
        canvas.drawText("YALL DIED", super.rect.left + (super.rect.width() / 2), super.rect.top + scaling.DrawY(700) + scrollPaddingTop + scrollMarginTop, TextGen.getFont(android.R.color.white, completeTextSize, 0, 0, R.font.grobold,255));
    }

    if(MainActivity.playerData.justUpgradedLVL){
        //run an level up animation
    }
}

public void onTouchEvent(MotionEvent e){
    float posX = e.getX();
    float posY = e.getY();

    switch (e.getActionMasked()) {
        case MotionEvent.ACTION_UP: {
            if (posX >= super.rect.left && posX <= super.rect.right && posY >= super.rect.top && posY <= super.rect.bottom) {
                if(battleWin){
                    MainActivity.SaveDataConsumableList(Globals.context);
                    MainActivity.SaveData(Globals.context);
                    MainActivity.GLOBALS.GSM = new GameStateManager(0); //Scanner
                }else{
                    MainActivity.SaveDataConsumableList(Globals.context);
                    MainActivity.SaveData(Globals.context);
                    MainActivity.GLOBALS.GSM = new GameStateManager(3); //Character Screen
                }
                return;
            }
        }
        break;
        case MotionEvent.ACTION_DOWN: {
        }
        break;
    }
}

Logcat输出

ITEMTYPE:      4:: X:-80: y:1000
ITEMTYPE:      2:: X:80: y:1000
ITEMTYPE:      4:: X:240: y:1000
ITEMTYPE:      3:: X:400: y:1000
ITEMTYPE:      4:: X:560: y:1000

问题原因排查

  1. 坐标适配错误:当前GameItem的x、y为固定屏幕坐标,但Dialog的显示区域从super.rect.left=540、super.rect.top=1080开始,大部分物品的x(-80、80、240)小于540,y(1000)小于1080,均处于Dialog可视区域外,仅少数物品可能部分/完全在区域内,被误认为同类型只显示一个。
  2. 实例重复风险:若Enemy的rewardsList中添加的是同一GameItem实例多次,循环更新坐标时会覆盖之前的位置,最终仅显示最后一次设置的坐标对应的物品。
  3. 共享资源冲突:若GameItem的draw方法使用静态Bitmap/Paint等资源,同类型物品绘制时会互相覆盖。

解决方案

1. 修正坐标计算,适配Dialog区域

修改构造函数中GameItem的坐标设置逻辑,基于Dialog的位置计算物品坐标:

// 构造函数中替换原坐标更新代码
int startX = super.rect.left + scaling.DrawX(40); // 左侧留边,避免贴Dialog边缘
int startY = super.rect.top + scaling.DrawY(1500); // 与奖励统计文本对齐,确保在Dialog内
int count = 0;
for (GameItem g: rewards) {
    g.updateXY(startX + (160*count), startY);
    Log.d("ITEMTYPE:",g.itemType+":: X:"+g.x+": y:"+g.y);
    count++;
}

2. 确保GameItem为独立实例

若Enemy的rewardsList存在重复实例,创建独立拷贝:

// 替换原rewards赋值逻辑
rewards = new ArrayList<>();
for (GameItem original : enemyObject.rewardsList) {
    // 根据GameItem的属性编写拷贝逻辑,示例:
    GameItem copy = new GameItem();
    copy.itemType = original.itemType;
    copy.x = original.x;
    copy.y = original.y;
    // 复制其他必要属性
    rewards.add(copy);
}
// 再执行坐标更新逻辑

3. 检查GameItem的draw方法

确保draw方法使用实例级资源,避免静态共享:

// GameItem类的draw方法示例
public void draw(Canvas canvas) {
    Paint itemPaint = new Paint();
    itemPaint.setAntiAlias(true);
    // 使用当前实例持有的Bitmap,而非静态Bitmap
    canvas.drawBitmap(this.itemBitmap, this.x, this.y, itemPaint);
}

内容的提问来源于stack exchange,提问作者user4655559

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:10:20