yangfanconan 发表于 2013-10-14 14:19:44

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

这节其实是将自定义渲染的。
不过我额外的补充一些内容。

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

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

其实在本库中

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.

Method Summary
voiddraw(BaseEntity owner, float posX, float posY, float velX, float velY, float headX, float headY)
          绘制
intinterval()
voidinterval(int interval)
          两帧之间的时间间隔,为0暂停。
intnextFrame()
         下一帧
intprevFrame()
      上一帧
这个也能看明白。
本库的bitmap中根本没有类似的功能。根据源码的分析解读,此类写的甚是简单。
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,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;       
        }
}


好吧,逼上梁山了,很多时候都是这样的。
所以自己写吧
写有两种方法,一种就是集成此类然后从写函数。
另一种就是直接根据此类中提供的一些方法,进行方法级别的修改。
在此我们先搞定方法级别的。
我们主要要实现的上下左右四个方向的行走。当然了就是给力。按一下方向键,人物做一下向这个方向行走的动画
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();
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++;
         }
      }
    }
}
}

当然这个程序还有一给问题,就是我们用的是车类进行的修改,而类会自动前进
这时候怎么让我们的主人公的步伐和前进速度一直
这时候有两种方法
一种是记录行走的方向,然后做一个方法进行动画分析
另一种是让动画不动的时候,速度为零,就可以了。
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();
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++;
         }
      }
    }
}
}

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

kerr 发表于 2013-10-14 15:13:58

准备自己做游戏机吗?

yangfanconan 发表于 2013-10-14 16:15:34

kerr 发表于 2013-10-14 15:13 static/image/common/back.gif
准备自己做游戏机吗?

游戏机?

friskit 发表于 2013-10-14 23:35:04

其实做过游戏的人一眼就能看出来,processing的框架就是个最简单的游戏引擎……;P。。

yangfanconan 发表于 2013-10-15 21:41:48

friskit 发表于 2013-10-14 23:35 static/image/common/back.gif
其实做过游戏的人一眼就能看出来,processing的框架就是个最简单的游戏引擎……。。

做过啥游戏?

friskit 发表于 2013-10-18 13:52:12

yangfanconan 发表于 2013-10-15 21:41 static/image/common/back.gif
做过啥游戏?

做着玩儿。。不盈利不出名。。纯研究技术

GW.wangshuo 发表于 2014-2-18 22:45:50

the constructor BitmapPic (CustomRenderer_01, String, int, int, int) is undefined   为什么出现这种状况, 在最后一页代码的38行报错

yangfanconan 发表于 2014-4-24 18:37:31

GW.wangshuo 发表于 2014-2-18 22:45 static/image/common/back.gif
the constructor BitmapPic (CustomRenderer_01, String, int, int, int) is undefined   为什么出现这种状 ...

你没有这个图片资源当然报错

uther2323134 发表于 2015-10-29 21:48:55

你好版主,能把你的这个库发给我吗,你这个修改被你修改过了?,我实在是无能为力了,我改了一天了,新版的我要让他图片也动态实在不行。新版的库与你的这个不同!

血阳 发表于 2016-1-28 15:41:42

感觉萌萌哒。
页: [1]
查看完整版本: Processing之旅-----【好玩的库之AI_for_2D_Games4】