2018年6月15日 星期五

[JAVA] 簡易鍵盤控制人物行走

※ 此程式碼並非優化版本,僅供個人學習用途,若有任何問題請告知。

※ 準備16個人物行走圖檔。
※ 程式碼延續自[JAVA]圖片移動小範例
※ 參考自【纯JAVA语言做RPG游戏】3.地图碰撞检测和角色行走的实现 -  - ITeye博客。
※ 已知bug:
1. 人物會閃爍。
2. 若按下不是設為條件的按鍵,人物會消失。

程式碼如下:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CharacterMove extends JFrame implements KeyListener {
private Container content;
private JPanel mainPane;
protected Image[] img_up, img_down, img_left, img_right;
protected Image img_stand_up, img_stand_down, img_stand_left, img_stand_right;
Graphics g;
final int INIT_X_POS = 400, INIT_Y_POS = 150; // 圖片初始位址
// X移動, Y移動, 圖片X, 圖片Y, 圖片寬度, 圖片高度
int SpeedX = 15, SpeedY = 15, imgX = INIT_X_POS, imgY = INIT_Y_POS,
imgW = 96, imgH = 96, up_count = 5, down_count = 5,
left_count = 5, right_count = 5, towards = 2,
up_now = 0, down_now = 0, left_now = 0, right_now = 0;
boolean up = false, down = false, left = false, right = false;
public CharacterMove() throws InterruptedException {
/* 視窗設定 */
super("test");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(false);
this.setBounds(200, 150, 1000, 500);
content = this.getContentPane();
mainPane = new JPanel();
mainPane.setLayout(new BorderLayout());
content.add(mainPane, BorderLayout.CENTER);
this.setVisible(true);
/* 圖片 */
MediaTracker t = new MediaTracker(this);
img_up = new Image[4];
img_down = new Image[4];
img_left = new Image[4];
img_right = new Image[4];
int a = 12, b = 0, c = 4, d = 8, temp = 0;
for(int i = 0; i < 4; ++i) {
img_up[i] = Toolkit.getDefaultToolkit().getImage("src\\p\\"+a+".png");
img_down[i] = Toolkit.getDefaultToolkit().getImage("src\\p\\"+b+".png");
img_left[i] = Toolkit.getDefaultToolkit().getImage("src\\p\\"+c+".png");
img_right[i] = Toolkit.getDefaultToolkit().getImage("src\\p\\"+d+".png");
t.addImage(img_up[i], temp);
t.addImage(img_down[i], ++temp);
t.addImage(img_left[i], temp+2);
t.addImage(img_right[i], temp+3);
++a; ++b; ++c; ++d; temp += 4;
}
img_stand_up = Toolkit.getDefaultToolkit().getImage("src\\p\\"+16+".png");
t.addImage(img_stand_up, 16);
img_stand_down = Toolkit.getDefaultToolkit().getImage("src\\p\\"+17+".png");
t.addImage(img_stand_down, 16);
img_stand_left = Toolkit.getDefaultToolkit().getImage("src\\p\\"+18+".png");
t.addImage(img_stand_left, 16);
img_stand_right = Toolkit.getDefaultToolkit().getImage("src\\p\\"+19+".png");
t.addImage(img_stand_right, 16);
t.waitForAll();
g = mainPane.getGraphics();
g.drawImage(img_stand_down, imgX, imgY, imgW, imgH, null);
this.addKeyListener(this);
}
public static void main(String[] args) throws InterruptedException {
new CharacterMove();
}
public void run() {
while (true) {
moveover();
try {Thread.sleep(20);}
catch (InterruptedException e) {e.printStackTrace();}
}
}
public void moveover() { //若是一輪已執行完
if(up) {
if (up_count >= 13) {up_count = 0;}
}
else if(down) {
if (down_count >= 13) {down_count = 0;}
}
else if(left) {
if(left_count >= 13) {left_count = 0;}
}
else if(right) {
if(right_count >= 13) {right_count = 0;}
}
}
public void move() { //判斷移動 切換圖片
if(up) {
if(up_count < 1) {
up_now = 0;
g.drawImage(img_up[0], imgX, imgY, imgW, imgH, null);
}
else if(up_count < 5) {
up_now = 1;
g.drawImage(img_up[1], imgX, imgY, imgW, imgH, null);
}
else if(up_count < 9) {
up_now = 2;
g.drawImage(img_up[2], imgX, imgY, imgW, imgH, null);
}
else {
up_now = 3;
g.drawImage(img_up[3], imgX, imgY, imgW, imgH, null);
}
}
else if(down) {
if(down_count < 1) {
down_now = 0;
g.drawImage(img_down[0], imgX, imgY, imgW, imgH, null);
}
else if(down_count < 5) {
down_now = 1;
g.drawImage(img_down[1], imgX, imgY, imgW, imgH, null);
}
else if(down_count < 9) {
down_now = 2;
g.drawImage(img_down[2], imgX, imgY, imgW, imgH, null);
}
else {
down_now = 3;
g.drawImage(img_down[3], imgX, imgY, imgW, imgH, null);
}
}
else if(left) {
if(left_count < 1) {
left_now = 0;
g.drawImage(img_left[0], imgX, imgY, imgW, imgH, null);
}
else if(left_count < 5) {
left_now = 1;
g.drawImage(img_left[1], imgX, imgY, imgW, imgH, null);
}
else if(left_count < 9) {
left_now = 2;
g.drawImage(img_left[2], imgX, imgY, imgW, imgH, null);
}
else {
left_now = 3;
g.drawImage(img_left[3], imgX, imgY, imgW, imgH, null);
}
}
else if(right) {
if(right_count < 1) {
right_now = 0;
g.drawImage(img_right[0], imgX, imgY, imgW, imgH, null);
}
else if(right_count < 5) {
right_now = 1;
g.drawImage(img_right[1], imgX, imgY, imgW, imgH, null);
}
else if(right_count < 9) {
right_now = 2;
g.drawImage(img_right[2], imgX, imgY, imgW, imgH, null);
}
else {
right_now = 3;
g.drawImage(img_right[3], imgX, imgY, imgW, imgH, null);
}
}
}
public void moveendtonext() { //角色所面向之方向
if(towards == 1) { //如果角色最後朝上
up_now = 3;
g.drawImage(img_up[3], imgX, imgY, imgW, imgH, null);
}
else if(towards == 2) { //如果朝下
down_now = 3;
g.drawImage(img_down[3], imgX, imgY, imgW, imgH, null);
}
else if(towards == 3) { //如果朝左
left_now = 3;
g.drawImage(img_left[3], imgX, imgY, imgW, imgH, null);
}
else if(towards == 4) { //如果朝右
right_now = 3;
g.drawImage(img_right[3], imgX, imgY, imgW, imgH, null);
}
}
public void notmove() { //當角色停下來時
if(towards == 1) { //如果角色最後朝上
up_now = 3;
g.drawImage(img_stand_up, imgX, imgY, imgW, imgH, null);
}
else if(towards == 2) { //如果朝下
down_now = 3;
g.drawImage(img_stand_down, imgX, imgY, imgW, imgH, null);
}
else if(towards == 3) { //如果朝左
left_now = 3;
g.drawImage(img_stand_left, imgX, imgY, imgW, imgH, null);
}
else if(towards == 4) { //如果朝右
right_now = 3;
g.drawImage(img_stand_right, imgX, imgY, imgW, imgH, null);
}
}
public void keyPressed(KeyEvent e) {
moveover();
notmove();
g.clearRect(imgX, imgY, imgW, imgH);
int key = e.getKeyCode();
/* 有作邊界判定 */
if(key == KeyEvent.VK_LEFT) { // 如(圖片的X位置-移動位置數)小於0 則等同於超出邊界
left = true;
imgX -= ((imgX - SpeedX) >= 0 ? SpeedX : imgX);
left_count++;
g.drawImage(img_left[left_now], imgX, imgY, imgW, imgH, null);
}
if(key == KeyEvent.VK_RIGHT) { // 如(圖片的X位置+圖片寬度+移動位置數)大於視窗寬度 則等同於超出邊界
right = true;
imgX += ((imgX + imgW + SpeedX) <= this.getWidth() ? SpeedX : (this.getWidth() - imgX - imgW));
right_count++;
g.drawImage(img_right[right_now], imgX, imgY, imgW, imgH, null);
}
if(key == KeyEvent.VK_UP) {
up = true;
imgY -= ((imgY - SpeedY) >= 0 ? SpeedY : imgY);
up_count++;
g.drawImage(img_up[up_now], imgX, imgY, imgW, imgH, null);
}
if(key == KeyEvent.VK_DOWN) {
down = true;
imgY += ((imgY + imgH + SpeedY) <= this.getHeight() ? SpeedY : (this.getHeight() - imgY - imgH));
down_count++;
g.drawImage(img_down[down_now], imgX, imgY, imgW, imgH, null);
}
/* 沒有作邊界判定 */
if(key == KeyEvent.VK_A) {
left = true;
imgX -= SpeedX;
left_count++;
g.drawImage(img_left[left_now], imgX, imgY, imgW, imgH, null);
}
if(key == KeyEvent.VK_D) {
right = true;
imgX += SpeedX;
right_count++;
g.drawImage(img_right[right_now], imgX, imgY, imgW, imgH, null);
}
if(key == KeyEvent.VK_W) {
up = true;
imgY -= SpeedY;
up_count++;
g.drawImage(img_up[up_now], imgX, imgY, imgW, imgH, null);
}
if(key == KeyEvent.VK_S) {
down = true;
imgY += SpeedY;
down_count++;
g.drawImage(img_down[down_now], imgX, imgY, imgW, imgH, null);
}
notmove();
g.clearRect(imgX, imgY, imgW, imgH);
move();
}
public void keyReleased(KeyEvent e) {
moveover();
g.drawImage(img_stand_down, imgX, imgY, imgW, imgH, null);
g.clearRect(imgX, imgY, imgW, imgH);
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
left = false;
towards = 3;
}
if (key == KeyEvent.VK_RIGHT) {
right = false;
towards = 4;
}
if (key == KeyEvent.VK_UP) {
up = false;
towards = 1;
}
if (key == KeyEvent.VK_DOWN) {
down = false;
towards = 2;
}
if (key == KeyEvent.VK_A) {
left = false;
towards = 3;
}
if (key == KeyEvent.VK_D) {
right = false;
towards = 4;
}
if (key == KeyEvent.VK_W) {
up = false;
towards = 1;
}
if (key == KeyEvent.VK_S) {
down = false;
towards = 2;
}
moveendtonext();
g.clearRect(imgX, imgY, imgW, imgH);
notmove();
}
public void keyTyped(KeyEvent arg0) {}
}

結果如下:


沒有留言:

張貼留言