Java1.8+Eclipse开发贪吃蛇游戏蛇身纹理更新及尾部纹理自定义问题
解决方案
问题核心根源:你当前所有蛇身纹理都绑定了全局的direction变量,所以只要头转向,所有身体的纹理都会同步变更。以下是可直接落地的修改方案:
第一步:新增必要属性和初始化逻辑
首先在类的属性区新增蛇身节点方向存储数组,以及尾部纹理资源:
// 原有属性下方新增 final char dir[] = new char[GAME_UNITS]; // 存储每个蛇身节点的独立移动方向 // 新增尾部四个方向纹理,提前把对应图片放到指定路径即可 Image tailup = new ImageIcon(this.getClass().getResource("/images/tailup.png")).getImage(); Image taild = new ImageIcon(this.getClass().getResource("/images/taild.png")).getImage(); Image tailr = new ImageIcon(this.getClass().getResource("/images/tailr.png")).getImage(); Image taill = new ImageIcon(this.getClass().getResource("/images/taill.png")).getImage();
然后在startGame()方法中初始化方向数组,和你默认的初始移动方向保持一致即可:
public void startGame() { newApple(); running = true; // 初始化所有蛇身节点的初始方向为向右 for(int i=0;i<GAME_UNITS;i++){ dir[i] = 'R'; } timer = new Timer(DELAY,this); timer.start(); }
第二步:修改move方法,同步递推节点方向
每次移动时不仅要传递坐标,也要把每个节点的方向往后传递,保证每个节点的方向都是自己移动时的真实方向:
public void move() { for(int i = bodyParts;i>0;i--) { x[i] = x[i-1]; y[i] = y[i-1]; dir[i] = dir[i-1]; // 方向同步向后递推 } dir[0] = direction; // 头节点更新为当前最新转向 switch(direction) { case 'U' : y[0] = y[0] - UNIT_SIZE; break; case 'D' : y[0] = y[0] + UNIT_SIZE; break; case 'L' : x[0] = x[0] - UNIT_SIZE; break; case 'R' : x[0] = x[0] + UNIT_SIZE; break; } }
第三步:重写draw方法的纹理渲染逻辑
现在每个节点用自己的独立方向判断纹理,同时单独识别最后一个节点加载尾部纹理:
public void draw(Graphics g) { if(running) { g.drawImage(apple, appleX,appleY, UNIT_SIZE, UNIT_SIZE, null, null); for(int i = 0;i< bodyParts; i++) { // 渲染头部纹理 if(i==0) { if(dir[i]=='U') g.drawImage(headup,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='R') g.drawImage(headr,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='L') g.drawImage(headl,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='D') g.drawImage(headd,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); } // 渲染尾部纹理:识别最后一个节点 else if(i == bodyParts -1) { if(dir[i]=='U') g.drawImage(tailup,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='R') g.drawImage(tailr,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='L') g.drawImage(taill,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='D') g.drawImage(taild,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); } // 渲染中间身体纹理 else { if(dir[i]=='U') g.drawImage(bodyup,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='R') g.drawImage(bodyr,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='L') g.drawImage(bodyl,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); else if(dir[i]=='D') g.drawImage(bodyd,x[i],y[i],UNIT_SIZE, UNIT_SIZE,null); } } // 原有分数渲染逻辑保持不变 g.setColor(Color.red); g.setFont(new Font("Arial",Font.BOLD,40)); FontMetrics metrics = getFontMetrics(g.getFont()); g.drawString("Score: "+applesEaten, (SCREEN_WIDTH - metrics.stringWidth("Score: "+applesEaten))/2, g.getFont().getSize()); }else { gameOver(g); } }
优化提示(可选)
如果想要更真实的效果,可以额外存储每个节点的上一次移动方向,判断当前方向和上一次方向的组合,加载对应的转角纹理即可。
内容的提问来源于stack exchange,提问作者imawake
相关产品推荐
相关产品推荐

