继续前两天的博客内容,接着写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;


/** *//**

 * <p>

 * Title: LoonFramework

 * </p>

 * <p>

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

 * </p>

 * <p>

 * Copyright: Copyright (c) 2008

 * </p>

 * <p>

 * Company: LoonFramework

 * </p>

 *

 * @author chenpeng

 * @email:[email]ceponline@yahoo.com.cn[/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;


/** *//**

 * <p>

 * Title: LoonFramework

 * </p>

 * <p>

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

 * </p>

 * <p>

 * Copyright: Copyright (c) 2008

 * </p>

 * <p>

 * Company: LoonFramework

 * </p>

 *

 * @author chenpeng

 * @email:[email]ceponline@yahoo.com.cn[/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;


/** *//**

 * <p>

 * Title: LoonFramework

 * </p>

 * <p>

 * Description:

 * </p>

 * <p>

 * Copyright: Copyright (c) 2008

 * </p>

 * <p>

 * Company: LoonFramework

 * </p>

 *

 * @author chenpeng

 * @email:[email]ceponline@yahoo.com.cn[/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);

            }

        });

    }


}


 以上……


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