继续前两天的博客内容,接着写Java中的ACT游戏实现,本来记得手里有C++版马里奥的角色和地图的,突然找不到丢那里了,凑活ps个GBA火影的图代替下……

运行效果如下:




此次重点演示了角色和地图的绘制……其实看过我以前写JAVA的RPG开发blog文章的早知道怎么弄的了……所以此次只帖代码……


Role.java:
package org.test.mario;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;

import org.loon.framework.game.p_w_picpath.Bitmap;

/** *//**
 *


 * Title: LoonFramework
 *


 *


 * Description:角色描述及绘制用类
 *


 *


 * Copyright: Copyright (c) 2008
 *


 *


 * Company: LoonFramework
 *


 *
 * @author chenpeng
 * @email:[email][email protected][/email]
 * @version 0.1
 */
public class Role ...{

    private double _x;

    private double _y;

    private double _vx;

    private double _vy;

    private boolean isFlat;

    private int _dir;

    private int _count;

    final static private Image role = new Bitmap("./role.gif").getImage();

    private Map _map;

    final static public int WIDTH = 40;

    final static public int HEIGHT = 40;

    final static private int SPEED = 6;

    final static private int JUMP_SPEED = 16;

    final static private int RIGHT = 0;

    final static private int LEFT = 1;

    public Role(double _x, double _y, Map _map) ...{
        this._x = _x;
        this._y = _y;
        this._map = _map;
        _vx = 0;
        _vy = 0;
        isFlat = false;
        _dir = RIGHT;
        _count = 0;

        AnimationThread thread = new AnimationThread();
        thread.start();
    }

    public void stop() ...{
        _vx = 0;
    }

    public void left() ...{
        _vx = -SPEED;
        _dir = LEFT;
    }

    public void right() ...{
        _vx = SPEED;
        _dir = RIGHT;
    }

    public void jump() ...{
        if (isFlat) ...{
            _vy = -JUMP_SPEED;
            isFlat = false;
        }
    }

    public void update() ...{
        //0.6为允许跳跃的高度限制,反值效果
        _vy += 0.6;

        double newX = _x + _vx;

        Point tile = _map.getTileHit(this, newX, _y);
        if (tile == null) ...{
            _x = newX;
        } else ...{
            if (_vx > 0) ...{

                _x = Map.tilesToPixels(tile.x) - WIDTH;
            } else if (_vx < 0) ...{
                _x = Map.tilesToPixels(tile.x + 1);
            }
            _vx = 0;
        }

        double newY = _y + _vy;
        tile = _map.getTileHit(this, _x, newY);
        if (tile == null) ...{
            _y = newY;
            isFlat = false;
        } else ...{
            if (_vy > 0) ...{
                _y = Map.tilesToPixels(tile.y) - HEIGHT;
                _vy = 0;
                isFlat = true;
            } else if (_vy < 0) ...{
                _y = Map.tilesToPixels(tile.y + 1);
                _vy = 0;
            }
        }
    }

    public void draw(Graphics g, int offsetX, int offsetY) ...{
        g.drawImage(role, (int) _x + offsetX, (int) _y + offsetY, (int) _x
                + offsetX + WIDTH, (int) _y + offsetY + HEIGHT, _count * WIDTH,
                _dir * HEIGHT, _count * WIDTH + WIDTH, _dir * HEIGHT + HEIGHT,
                null);
    }

    public double getX() ...{
        return _x;
    }

    public double getY() ...{
        return _y;
    }

    private class AnimationThread extends Thread ...{
        public void run() ...{
            while (true) ...{
                if (_count == 0) ...{
                    _count = 1;
                } else if (_count == 1) ...{
                    _count = 0;
                }

                try ...{
                    Thread.sleep(300);
                } catch (InterruptedException e) ...{
                    e.printStackTrace();
                }
            }
        }
    }

}

Map.java:
package org.test.mario;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;

import org.loon.framework.game.p_w_picpath.Bitmap;

/** *//**
 *


 * Title: LoonFramework
 *


 *


 * Description:地图绘制及描述用类
 *


 *


 * Copyright: Copyright (c) 2008
 *


 *


 * Company: LoonFramework
 *


 *
 * @author chenpeng
 * @email:[email][email protected][/email]
 * @version 0.1
 */
public class Map ...{

    // 在以前的blog文章中我介绍过,游戏开发中通常以数组描述地图
    // 此处1描绘为一个障碍物,0描绘为一个可通行空间
    final static public int TILE_SIZE = 32;

    final static public int ROW = 20;

    final static public int COL = 30;

    final static public int WIDTH = TILE_SIZE * COL;

    final static public int HEIGHT = TILE_SIZE * ROW;

    final static public double GRAVITY = 0.6;

    // 地图描述
    final static private int[][] map = ...{
            ...{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                    2, 2, 2, 2, 2, 2, 2, 2 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
                    2, 2, 2, 2, 2, 2, 2, 1 },
            ...{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 2, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                    2, 2, 2, 2, 2, 2, 2, 1 } };

    final static private Image tile = new Bitmap("./tile_0.gif").getImage();

    final static private Image tile2 = new Bitmap("./tile_1.gif").getImage();

    /** *//**
     * 构造函数
     *
     */
    public Map() ...{
    }

    public void draw(Graphics g, int offsetX, int offsetY) ...{
        int firstTileX = pixelsToTiles(-offsetX);
        int lastTileX = firstTileX + pixelsToTiles(Main._WIDTH) + 1;
        lastTileX = Math.min(lastTileX, COL);
        int firstTileY = pixelsToTiles(-offsetY);
        int lastTileY = firstTileY + pixelsToTiles(Main._HEIGHT) + 1;
        lastTileY = Math.min(lastTileY, ROW);

        for (int i = firstTileY; i < lastTileY; i++) ...{
            for (int j = firstTileX; j < lastTileX; j++) ...{
                // 转换map标识
                switch (map[i][j]) ...{
                case 1: // 绘制砖地

                    g.drawImage(tile, tilesToPixels(j) + offsetX,
                            tilesToPixels(i) + offsetY, null);
                    break;
                case 2:
                    g.drawImage(tile2, tilesToPixels(j) + offsetX,
                            tilesToPixels(i) + offsetY, null);
                    break;
                }
            }
        }
    }

    /** *//**
     * 换算角色与地板的撞击,并返回Point用以描述新的x,y
     *
     * @param player
     * @param newX
     * @param newY
     * @return
     */
    public Point getTileHit(Role player, double newX, double newY) ...{

        newX = Math.ceil(newX);
        newY = Math.ceil(newY);

        double fromX = Math.min(player.getX(), newX);
        double fromY = Math.min(player.getY(), newY);
        double toX = Math.max(player.getX(), newX);
        double toY = Math.max(player.getY(), newY);

        int fromTileX = pixelsToTiles(fromX);
        int fromTileY = pixelsToTiles(fromY);
        int toTileX = pixelsToTiles(toX + Role.WIDTH - 1);
        int toTileY = pixelsToTiles(toY + Role.HEIGHT - 1);

        for (int x = fromTileX; x <= toTileX; x++) ...{
            for (int y = fromTileY; y <= toTileY; y++) ...{

                if (x < 0 || x >= COL) ...{
                    return new Point(x, y);
                }
                if (y < 0 || y >= ROW) ...{
                    return new Point(x, y);
                }
                if (map[y][x] == 1 || map[y][x] == 2) ...{
                    return new Point(x, y);
                }
            }
        }

        return null;
    }

    /** *//**
     * 将Tiles转为Pixels
     *
     * @param pixels
     * @return
     */
    public static int pixelsToTiles(double pixels) ...{
        return (int) Math.floor(pixels / TILE_SIZE);
    }

    /** *//**
     * 将Pixels转为Tiles
     *
     * @param pixels
     * @return
     */
    public static int tilesToPixels(int tiles) ...{
        return tiles * TILE_SIZE;
    }
}


Main.java
package org.test.mario;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import org.loon.framework.game.p_w_picpath.Bitmap;

/** *//**
 *


 * Title: LoonFramework
 *


 *


 * Description:
 *


 *


 * Copyright: Copyright (c) 2008
 *


 *


 * Company: LoonFramework
 *


 *
 * @author chenpeng
 * @email:[email][email protected][/email]
 * @version 0.1
 */
public class Main extends Panel implements Runnable, KeyListener ...{

    /** *//**
     *
     */
    private static final long serialVersionUID = 1L;

    public static final int _WIDTH = 640;

    public static final int _HEIGHT = 480;

    private Map _map;

    private Role _role;

    private Thread _sleep;

    private Image _screen = null;

    private Graphics _graphics = null;

    // 方向控制,由于是自然落体所以没有down
    private boolean LEFT;

    private boolean RIGHT;

    private boolean UP;

    public Main() ...{
        setSize(_WIDTH, _HEIGHT);
        setFocusable(true);
        _screen = new Bitmap(_WIDTH, _HEIGHT).getImage();
        _graphics = _screen.getGraphics();
        _map = new Map();
        
        _role = new Role(190, 40, _map);

        // 监听窗体
        addKeyListener(this);

        // 启动线程
        _sleep = new Thread(this);
        _sleep.start();
    }

    /** *//**
     * 运行
     */
    public void run() ...{
        while (true) ...{
            //改变方向
            if (LEFT) ...{
                _role.left();
            } else if (RIGHT) ...{
                _role.right();
            } else ...{
                _role.stop();
            }
            if (UP) ...{
                _role.jump();
            }
            _role.update();
            repaint();
            try ...{
                Thread.sleep(20);
            } catch (InterruptedException e) ...{
                e.printStackTrace();
            }
        }
    }

    public void update(Graphics g) ...{
        paint(g);
    }

    public void paint(Graphics g) ...{
   
        _graphics.setColor(Color.BLACK);
        _graphics.fillRect(0, 0, _WIDTH, _HEIGHT);

        int offsetX = _WIDTH / 2 - (int)_role.getX();
 
        offsetX = Math.min(offsetX, 0);
        offsetX = Math.max(offsetX, _WIDTH - Map.WIDTH);

        int offsetY =_HEIGHT / 2 - (int)_role.getY();
 
        offsetY = Math.min(offsetY, 0);
        offsetY = Math.max(offsetY, _HEIGHT - Map.HEIGHT);


        _map.draw(_graphics, offsetX, offsetY);

   
        _role.draw(_graphics, offsetX, offsetY);
       
        g.drawImage(_screen, 0,0,null);
    }

    public void keyPressed(KeyEvent e) ...{
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT) ...{
            LEFT = true;
        }
        if (key == KeyEvent.VK_RIGHT) ...{
            RIGHT = true;
        }
        if (key == KeyEvent.VK_UP) ...{
            UP = true;
        }
    }

    public void keyReleased(KeyEvent e) ...{
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT) ...{
            LEFT = false;
        }
        if (key == KeyEvent.VK_RIGHT) ...{
            RIGHT = false;
        }
        if (key == KeyEvent.VK_UP) ...{
            UP = false;
        }
    }

    public void keyTyped(KeyEvent e) ...{
    }

    public static void main(String[] args) ...{
        Frame frame = new Frame();
        frame.setTitle("Java来做马里奥(2)—木叶传承");
        frame.setSize(_WIDTH, _HEIGHT+20);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.add(new Main());
        frame.setVisible(true);
        frame.addWindowListener(new WindowAdapter() ...{
            public void windowClosing(WindowEvent e) ...{
                System.exit(0);
            }
        });
    }

}

 以上……

突然觉得这样做也挺有意思的,准备让木叶丸踩三代玩,啊哈哈哈……(众人曰:神经病)||||