极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 26789|回复: 9

Processing之旅-----【好玩的库之AI_for_2D_Games4】

[复制链接]
发表于 2013-10-14 14:19:44 | 显示全部楼层 |阅读模式
这节其实是将自定义渲染的。
不过我额外的补充一些内容。

平面行走图是RPG等类型游戏常用的图片资源。
类似这种

问题是这个库貌似不支持多个动作集成在一个图片中,其实这种情况下怎么办、最好当然是提供想对象的资源,但这也不好
因为这个库里面AI是主要的对渲染这部分基本上没什么特殊的功能。不方便。
所以我们要自己动手写一下怎么支持这个功能。

其实在本库中
[size=+2][size=1em]Constructor Summary
BitmapPic(PApplet papp, String fname)
          Single image for all frames
BitmapPic(PApplet papp, String fname, int nCols, int nRows, int interval)
          An animated image.
[size=11.199999809265137px]
[size=+2][size=1em]Method Summary
[size=-1][size=1em] void
draw(BaseEntity owner, float posX, float posY, float velX, float velY, float headX, float headY)
          绘制
[size=-1][size=1em] int
[size=-1][size=1em] void
interval(int interval)
          两帧之间的时间间隔,为0暂停。
[size=-1][size=1em] int
nextFrame()
         下一帧
[size=-1][size=1em] int
prevFrame()
        上一帧
[size=11.199999809265137px] 这个也能看明白。
本库的bitmap中根本没有类似的功能。根据源码的分析解读,此类写的甚是简单。
[pre lang="java" line="1"]package game2dai.entityshapes.ps;

import game2dai.entities.BaseEntity;
import processing.core.PApplet;
import processing.core.PImage;

/**
* The entity graphic comes from an image file.
*
* @author Peter Lager
*
*/
public class BitmapPic extends PicturePS {

        PImage[] img;

        int lastTime = 0, elapsedTime = 0;
        int interval = 0;
        int frameNo = 0;
       
        /**
         * Single image for all frames
         * @param papp
         * @param fname the name of the bitmap image file
         */
        public BitmapPic(PApplet papp, String fname){
                super(papp);
                img = ImageBank.getImage(papp, fname);
        }
       
        /**
         * An animated image. <br>
         * The image frames are stored as tiles within a single image
         *  
         * @param papp
         * @param fname the name of the bitmap image file
         * @param nCols number of tiles horizontally
         * @param nRows number of rows vertically
         * @param interval the time (milliseconds) between image frames
         */
        public BitmapPic(PApplet papp, String fname, int nCols, int nRows, int interval){
                super(papp);
                img = ImageBank.getImage(papp, fname, nCols, nRows);
                lastTime = app.millis();
                elapsedTime = 0;
                this.interval = (nCols* nRows > 1) ? interval : 0;
        }
       
       
        @Override
        public void draw(BaseEntity owner, float posX, float posY, float velX,
                        float velY, float headX, float headY) {
                // Draw and hints that are specified and relevant
                if(hints != 0){
                        Hints.hintFlags = hints;
                        Hints.draw(app, owner, velX, velY, headX, headY);
                }
                // Determine the angle the entity is facing
                float angle = PApplet.atan2(headY, headX);

                // If this an animated image then update the animation
                if(interval > 0){
                        int ctime = app.millis();
                        while(ctime > lastTime + interval){
                                lastTime += interval;
                                frameNo++;
                        }
                        frameNo %= img.length;
                }

                // Prepare to draw the entity               
                app.pushStyle();
                app.imageMode(PApplet.CENTER);
                app.pushMatrix();
                app.translate(posX, posY);
                app.rotate(angle);

                // Draw the entity               
                app.image(img[frameNo],0,0);

                // Finished drawing
                app.popMatrix();
                app.popStyle();
        }

        /**
         * Set the number of milliseconds between frames. <br>
         * Negative values will be treated as zero which will cause the animation to pause.
         *
         * @param interval
         */
        public void interval(int interval){
                if(interval <= 0)
                        this.interval = 0;
                else
                        this.interval = interval;
        }
       
        public int interval(){
                return interval;
        }
       
        /**
         * Use next frame in the animation
         * @return this renderer
         */
        public int nextFrame(){
                frameNo++;
                frameNo %= img.length;
                return frameNo;
        }
       
        /**
         * Use previous frame in the animation
         * @return this renderer
         */
        public int prevFrame(){
                frameNo += img.length - 1;
                frameNo %= img.length;
                return frameNo;       
        }
}
[/code]

好吧,逼上梁山了,很多时候都是这样的。
所以自己写吧
写有两种方法,一种就是集成此类然后从写函数。
另一种就是直接根据此类中提供的一些方法,进行方法级别的修改。
在此我们先搞定方法级别的。
我们主要要实现的上下左右四个方向的行走。当然了就是给力。按一下方向键,人物做一下向这个方向行走的动画
[pre lang="processing" line="1"]import game2dai.entities.*;
import game2dai.entityshapes.ps.*;
import game2dai.maths.*;
import game2dai.*;
import game2dai.entityshapes.*;
import game2dai.fsm.*;
import game2dai.steering.*;
import game2dai.utils.*;
import game2dai.graph.*;
// AnimRenderer_01
World world;
StopWatch sw;
Vehicle tank;
Vector2D target = new Vector2D();
BitmapPic view;
BitmapPic viewshang;
BitmapPic viewxia;
BitmapPic viewzuo;
BitmapPic viewyou;
Vector2D origin;
int movei=0;;
public void setup() {
  size(600, 320);
  world = new World(width, height);
  sw = new StopWatch();
  // Create the mover
  tank = new Vehicle(new Vector2D(width/2, height/2), // position
    40,                 // collision radius
    new Vector2D(0, 0), // velocity
    40,                 // maximum speed
    new Vector2D(0, 0), // headinga
    15,                 // mass
    90f,               // turning rate
    1000                // max force
  );
  // What does this mover look like
  view = new BitmapPic(this, "nvzhujiao.png", 4,4,0);   
  tank.renderer(view);
  // Finally we want to add this to our game domain
  world.add(tank);
  sw.reset();
}

public void draw() {
  double elapsedTime = sw.getElapsedTime();
  
  tank.AP().arriveOn(target);
  origin=tank.AP().getFeelers()[1];
  float speed = (float) tank.speed();
  float maxSpeed = (float) tank.maxSpeed();
  if (speed > 1) {
    int newInterval = (int) map(speed, 0, maxSpeed, 600, 40);
   // view.interval(newInterval);
  }
  else {
    //view.interval(0);
  }
  world.update(elapsedTime);
  background(218, 140, 54);
  world.draw();
}

void keyPressed()
{
  switch (keyCode)
  {
   
    case 87 :
    {
      
      if(movei>=12&&movei<15)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(12);
      
      }
       println(movei);
       target.set(origin.x, 0);
       break;
    }

   
    case 83 :
    {
      
      if(movei>=0&&movei<3)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(0);
      }
      println(movei);
      target.set(origin.x, height);
      break;
    }  
    case 65 :
    {
      if(movei>=4&&movei<7)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(4);
      }
      target.set(0, origin.y);
      break;
    }
    case 68 :
    {
     if(movei>=8&&movei<11)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(8);
      }
      target.set(width, origin.y);
      break;
    }
    default :
      println("keyCode: "+keyCode);
    break;  
         
  }

}
void changeMovei(int needto)
{
  int moveitemp=movei;
  if(needto>=0&&needto<=15)
  {
    if(moveitemp==needto)
    {

    }
    else
    {
      if(moveitemp>needto)
      {//movei>needto
         for(int i=0;i<moveitemp-needto;i++)
         {
           view.prevFrame();
           movei--;
         }
      }
      else
      {//movei<needto
         for(int i=0;i<needto-moveitemp;i++)
         {
           view.nextFrame();
           movei++;
         }
      }
    }
  }
}[/code]

当然这个程序还有一给问题,就是我们用的是车类进行的修改,而类会自动前进
这时候怎么让我们的主人公的步伐和前进速度一直
这时候有两种方法
一种是记录行走的方向,然后做一个方法进行动画分析
另一种是让动画不动的时候,速度为零,就可以了。
[pre lang="processing" line="1"]import game2dai.entities.*;
import game2dai.entityshapes.ps.*;
import game2dai.maths.*;
import game2dai.*;
import game2dai.entityshapes.*;
import game2dai.fsm.*;
import game2dai.steering.*;
import game2dai.utils.*;
import game2dai.graph.*;
// AnimRenderer_01
World world;
StopWatch sw;
Vehicle tank;
Vector2D target = new Vector2D();
BitmapPic view;
BitmapPic viewshang;
BitmapPic viewxia;
BitmapPic viewzuo;
BitmapPic viewyou;
Vector2D origin;
int movei=0;;
int fangxiang=0;//0下1上2左3右
public void setup() {
  size(600, 320);
  world = new World(width, height);
  sw = new StopWatch();
  // Create the mover
  tank = new Vehicle(new Vector2D(width/2, height/2), // position
    40,                 // collision radius
    new Vector2D(0, 0), // velocity
    40,                 // maximum speed
    new Vector2D(0, 0), // headinga
    15,                 // mass
    90f,               // turning rate
    1000                // max force
  );
  // What does this mover look like
  view = new BitmapPic(this, "nvzhujiao.png", 4,4,0);   
  tank.renderer(view);
  // Finally we want to add this to our game domain
  world.add(tank);
  sw.reset();
}

public void draw() {
  double elapsedTime = sw.getElapsedTime();
  
  tank.AP().arriveOn(target);
  origin=tank.AP().getFeelers()[1];
  float speed = (float) tank.speed();
  float maxSpeed = (float) tank.maxSpeed();
  if (speed > 1) {
    int newInterval = (int) map(speed, 0, maxSpeed, 600, 40);
    //view.interval(newInterval);
    DonghuaFenxi();
  }
  else {
    //view.interval(0);
  }
  world.update(elapsedTime);
  background(218, 140, 54);
  world.draw();
}

void keyPressed()
{
  switch (keyCode)
  {
   
    case 87 :
    {
      fangxiang=1;
       break;
    }

   
    case 83 :
    {
      fangxiang=0;
      break;
    }  
    case 65 :
    {
      fangxiang=2;
      break;
    }
    case 68 :
    {
     fangxiang=3;
      break;
    }
    default :
      println("keyCode: "+keyCode);
    break;  
         
  }

}
void DonghuaFenxi()
{
   switch (fangxiang)
  {
   
    case 1 :
    {
      
      if(movei>=12&&movei<15)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(12);
      
      }
       println(movei);
       target.set(origin.x, 0);
       break;
    }

   
    case 0 :
    {
      
      if(movei>=0&&movei<3)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(0);
      }
      println(movei);
      target.set(origin.x, height);
      break;
    }  
    case 2 :
    {
      if(movei>=4&&movei<7)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(4);
      }
      target.set(0, origin.y);
      break;
    }
    case 3 :
    {
     if(movei>=8&&movei<11)
      {
          view.nextFrame();
          movei++;
      }
      else
      {
        changeMovei(8);
      }
      target.set(width, origin.y);
      break;
    }
    default :
      println("keyCode: "+keyCode);
    break;  
         
  }
}
void changeMovei(int needto)
{
  int moveitemp=movei;
  if(needto>=0&&needto<=15)
  {
    if(moveitemp==needto)
    {

    }
    else
    {
      if(moveitemp>needto)
      {//movei>needto
         for(int i=0;i<moveitemp-needto;i++)
         {
           view.prevFrame();
           movei--;
         }
      }
      else
      {//movei<needto
         for(int i=0;i<needto-moveitemp;i++)
         {
           view.nextFrame();
           movei++;
         }
      }
    }
  }
}[/code]

效果是动态的,截图开不出来。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2013-10-14 15:13:58 | 显示全部楼层
准备自己做游戏机吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-14 16:15:34 | 显示全部楼层
kerr 发表于 2013-10-14 15:13
准备自己做游戏机吗?

游戏机?
回复 支持 反对

使用道具 举报

发表于 2013-10-14 23:35:04 | 显示全部楼层
其实做过游戏的人一眼就能看出来,processing的框架就是个最简单的游戏引擎……。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-10-15 21:41:48 | 显示全部楼层
friskit 发表于 2013-10-14 23:35
其实做过游戏的人一眼就能看出来,processing的框架就是个最简单的游戏引擎……。。

做过啥游戏?
回复 支持 反对

使用道具 举报

发表于 2013-10-18 13:52:12 | 显示全部楼层
yangfanconan 发表于 2013-10-15 21:41
做过啥游戏?

做着玩儿。。不盈利不出名。。纯研究技术
回复 支持 反对

使用道具 举报

发表于 2014-2-18 22:45:50 | 显示全部楼层
the constructor BitmapPic (CustomRenderer_01, String, int, int, int) is undefined   为什么出现这种状况, 在最后一页代码的38行报错
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-4-24 18:37:31 | 显示全部楼层
GW.wangshuo 发表于 2014-2-18 22:45
the constructor BitmapPic (CustomRenderer_01, String, int, int, int) is undefined   为什么出现这种状 ...

你没有这个图片资源当然报错
回复 支持 反对

使用道具 举报

发表于 2015-10-29 21:48:55 | 显示全部楼层
你好版主,能把你的这个库发给我吗,你这个修改被你修改过了?,我实在是无能为力了,我改了一天了,新版的我要让他图片也动态实在不行。新版的库与你的这个不同!
回复 支持 反对

使用道具 举报

发表于 2016-1-28 15:41:42 | 显示全部楼层
感觉萌萌哒。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-19 11:22 , Processed in 0.044271 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表