Mophun & J2ME 的游戏开发之旅(四)

类别:编程语言 点击:0 评论:0 推荐:

CASE STUDY:
MyMSnakeS3D:我的手机贪吃蛇游戏类3D版本
技巧:通过2D到3D的投影,画出类3D效果.

/////////////////////////////////////////////////////////////////////////////////////RES.TXT

#include <datacert.h>

INFO METAINFO
{
 "Title"    : "MyMSnakeS3D"
 "Vendor"   : "[email protected]"
 "Copyright info" : "美元右括号"
 "Program version" : "0.02"
 "Help"    : "Help me!"
}

// ***********************************************************************************************
// CERTIFICATION STUFF
// ***********************************************************************************************
DATACERT_AND_SECURITY_RESOURCE
CREDITS DATA { FILL 32,0}

SECTION DATA
// *****************************************
// THE FONT
// *****************************************
FONTA  DATA      "gfx/systemfont4x6.fnt"

TILES  TILESET 8 8 FORMAT RGB332 "gfx/tiles.bmp"
MYSPRITE SPRITE FORMAT RGB332  "gfx/sprite.bmp"
MY_M_SNAKE_3D_TITLE SPRITE FORMAT RGB332  "gfx/title.bmp"

 


/////////////////////////////////////////////////////////////////////////////////////MyMSnake.mak
# *****************************************
#
# NAME:    makefile
# PROJECT: MyMSnakeS3D我的移动贪吃蛇类3D
# DATE:    2004-10-09
# BY:      Gaogao [email protected]
# version : 0.02
# 美元右括号
# +加入类3D 的图像模式
# *****************************************

# *****************************************
# FLAGS
# *****************************************
CFLAGS = -O2 -Wall -fvstudio

# *****************************************
# OBJEKTFILES
# *****************************************
OBJS = res.o MyMSnake.o

all: MyMSnake.mpn

# *****************************************
# RESOURCE
# *****************************************
res.o: res.txt
 morc -v res.txt

# *****************************************
# COMPILER
# *****************************************
.c.o:
 pip-gcc -c $(CFLAGS) -o $@ $<

# *****************************************
# LINKER
# *****************************************
MyMSnake.mpn: $(OBJS) 
 pip-gcc -o $@ $(OBJS) -mstack=1024 -mdata=10000 -ldatacert -s



/////////////////////////////////////////////////////////////////////////////////////MyMSnake.h

// *********************************************
// 贪吃蛇的Mophun版本for SE T618
// @author 美元右括号
// @version 0.02
// @connect [email protected]
// +加入类3D 的图像模式
// *********************************************

#ifndef MYMSNAKE_H
#define MYMSNAKE_H

#include <vmgp.h>
#include "res.h"
// *********************************************
// GLOBAL  variables for MyMSnake GAME
// *********************************************
#define TRUE 1
#define FALSE 0
// 屏幕宽
int32_t   screen_width   = 0;
//BUG IN 0.01
//#define SCREEN_HEIGHT = 160;
#define SCREEN_WIDTH 128
// 屏幕高
int32_t   screen_height  = 0;
//BUG IN 0.01
//#define SCREEN_HEIGHT = 160;
#define SCREEN_HEIGHT 160
// 字体设置
VMGPFONT FontA;

// 蛇身体元素的大小
#define SNAKE_ELEMENT_SIZE 8
// 方向设置
#define UP_DIRECTION 0
#define DOWN_DIRECTION 1
#define LEFT_DIRECTION 2
#define RIGHT_DIRECTION 3
// 地图的初始状态
#define EMPTY 0
// 地图被Snake1个身体映射的状态
#define SNAKE_IN 1
// 地图被Snake2个身体映射的状态
#define SNAKE_OVERFLOW 2
// 蛇的身体的存储
typedef struct 
{
 struct SnakeElement * next;
 int16_t x;
 int16_t y;
 int16_t direction;
}SnakeElement;

// Snake的头和尾指针
SnakeElement * snakeHead, * snakeTail;

// 蛇的食物的存储
typedef struct
{
 int16_t x;
 int16_t y;
 int16_t var;
}SnakeFood;

// 食物是否被吃
int16_t isFoodBeEaten = FALSE;

// 可爱的贪吃蛇是不是因为贪吃而死亡?
int16_t isTheSnakeDead = FALSE;

// 地图的宽
#define X_MAX 16
// 地图的高
#define Y_MAX 20
// 地图存储
int16_t backgroundArray[Y_MAX][X_MAX];

//贪吃蛇的初始位置设定
#define X_INIT 8
#define Y_INIT 10

//游戏计数器
#define LEVEL_NUM 10
int16_t level_counter[] = {30, 25, 20, 18, 16, 13, 11, 10, 5, 3};
                           ////////LEVEL_NUM
int16_t currentLevel = 0;
int16_t counter = 0;

//食物的初始位置
SnakeFood snakeFood;
#define FRAME_CONTROLER 30


// 方法
void initGame(void);
// 初始化屏幕
void GetScreenSize(void);
// 初始化字体
void InitFont(void);
// 地图初始化
void initMap(void);
// 贪吃蛇初始化
void initSnake(void);
// 移动贪吃蛇
void moveSnake(void);
// 生成食物
void generateFood(void);
// 绘制游戏场景
void paintObjects(void);
// 销毁一切游戏中的内存碎片
void destroyObjects(void);

// S3D效果
// S3D坐标获得
int16_t getS3DX(int16_t x, int16_t y);
int16_t getS3DY(int16_t y);

#endif

/////////////////////////////////////////////////////////////////////////////////////MyMSnake.c


// *********************************************
// 贪吃蛇的Mophun版本for SE T618
// @author 美元右括号
// @version 0.02
// @connect [email protected]
// 加入类3D 的图像模式
// *********************************************
#include "MyMSnake.h"


void initGame(void)
{
 isTheSnakeDead = FALSE;
 isFoodBeEaten = FALSE;
 currentLevel = 0;
 counter = 0;
}

// *******************************************************
// 获得屏幕尺寸
// *******************************************************
void GetScreenSize(void)
{
 VIDEOCAPS videocaps;
 videocaps.size = sizeof(VIDEOCAPS);
 if(vGetCaps(CAPS_VIDEO,&videocaps))
 {
  screen_width  = videocaps.width;
  screen_height = videocaps.height;
 }
}
// *******************************************************
// 新建字体
// *******************************************************
void InitFont(void)
{
 FontA.width    = 4;
 FontA.height   = 6;
 FontA.bpp      = 1;
 FontA.palindex = 0;
 FontA.chartbl   = FONTA + 16;
 FontA.fontdata = FONTA + 16 + 256; 
 vSetActiveFont(&FontA);
}
// 地图初始化
void initMap(void)
{
 int i = 0, j = 0;
 for (i = 0; i < Y_MAX; i++)
 {
  for (j = 0; j < X_MAX; j++)
  {
   backgroundArray[i][j] = EMPTY;
  }
 }
}
// 贪吃蛇初始化
void initSnake(void)
{

 SnakeElement *temp;
 snakeTail = (SnakeElement *)malloc(sizeof(SnakeElement));
 snakeTail->x = X_INIT - 3;
 snakeTail->y = Y_INIT;
 snakeTail->direction = RIGHT_DIRECTION;
 snakeTail->next = (SnakeElement *)malloc(sizeof(SnakeElement));
 temp = snakeTail->next;
 temp->x = X_INIT - 2;
 temp->y = Y_INIT;
 temp->direction = RIGHT_DIRECTION;
 temp->next = (SnakeElement *)malloc(sizeof(SnakeElement));
 temp = temp->next;
 temp->x = X_INIT - 1;
 temp->y = Y_INIT;
 temp->direction = RIGHT_DIRECTION;
 temp->next = (SnakeElement *)malloc(sizeof(SnakeElement));
 temp = temp->next;
 temp->x = X_INIT;
 temp->y = Y_INIT;
 temp->direction = RIGHT_DIRECTION;
 temp->next = NULL;
 snakeHead = temp;
 backgroundArray[Y_INIT][ X_INIT - 3] = SNAKE_IN;
 backgroundArray[Y_INIT][ X_INIT - 2] = SNAKE_IN;
 backgroundArray[Y_INIT][ X_INIT - 1] = SNAKE_IN;
 backgroundArray[Y_INIT][ X_INIT - 0] = SNAKE_IN;
 
}
// 移动贪吃蛇
void moveSnake(void)
{
 //清理不backgroundArray;
 SnakeElement * temp = snakeTail;
 while (temp!=NULL)
 {
  backgroundArray[temp->y][temp->x] = EMPTY; 
  temp = temp->next;
 }
 //移动Snake
 SnakeElement * tempTailToo = (SnakeElement *)malloc(sizeof(SnakeElement));
 tempTailToo->x = snakeTail->x;
 tempTailToo->y = snakeTail->y;
 tempTailToo->direction = snakeTail->direction;

 SnakeElement * tempNewHead = snakeTail;
 snakeTail = snakeTail->next;
 tempNewHead->next = NULL;

 switch (snakeHead->direction)
 {
 case UP_DIRECTION:
  tempNewHead->y = snakeHead->y - 1;
  tempNewHead->x = snakeHead->x;
  tempNewHead->direction = snakeHead->direction;
 break;
 case DOWN_DIRECTION:
  tempNewHead->y = snakeHead->y + 1;
  tempNewHead->x = snakeHead->x;
  tempNewHead->direction = snakeHead->direction;
 break;
 case LEFT_DIRECTION:
  tempNewHead->x = snakeHead->x - 1;
  tempNewHead->y = snakeHead->y; 
  tempNewHead->direction = snakeHead->direction;
 break;
 case RIGHT_DIRECTION:
  tempNewHead->x = snakeHead->x + 1;
  tempNewHead->y = snakeHead->y; 
  tempNewHead->direction = snakeHead->direction;  
 break;
 }
 snakeHead->next = tempNewHead;
 snakeHead = snakeHead->next;
 if (snakeHead->x == snakeFood.x
  &&
  snakeHead->y == snakeFood.y
  )
 {
  isFoodBeEaten = TRUE;
 }
 if (isFoodBeEaten == TRUE)
 {
  //isFoodBeEaten = FALSE;
  tempTailToo->next = snakeTail;
  snakeTail = tempTailToo;
  generateFood();
 }
 
 //移动后

 temp = snakeTail;
 while (temp!=NULL)
 {
  backgroundArray[temp->y][temp->x] += SNAKE_IN;
  if (backgroundArray[temp->y][temp->x] > SNAKE_IN)
  {
   isTheSnakeDead = TRUE;
  }
  temp = temp->next;
 } 
 if (snakeHead->x < 0 ||
  snakeHead->y < 0 ||
  snakeHead->x >= X_MAX ||
  snakeHead->y >= Y_MAX)
 {
  isTheSnakeDead = TRUE;
 }
}
// 生成食物
void generateFood(void)
{
 if (isFoodBeEaten == FALSE)
 {
  return;
 }
 else
 {
  int x;
  int y;

  vSetRandom(vGetTime());
  x = abs(vGetRandom() % X_MAX);
  vSetRandom(vGetTime());
  y = abs(vGetRandom() % Y_MAX);
  if (backgroundArray[y][x] == EMPTY)
  {
   snakeFood.x = x;
   snakeFood.y = y;
   snakeFood.var = 1;
   isFoodBeEaten = FALSE;
  }
  generateFood();
  
 }
}

// 绘制游戏场景
void paintObjects(void)
{
 SnakeElement *temp = snakeTail;
 // ---- Init Graphics --------------------------------
 vSetClipWindow(0,0,screen_width,screen_height);   // Set Maximum Clipwindow
 vSetForeColor(vRGB(255,255,255));      // White forecolor
 vSetBackColor(vRGB(0,0,0));        // Black background
 vClearScreen(vRGB(0,0,0));        // Fill Screen with black
 vSetTransferMode(MODE_TRANS);       // Set transfer mode to transparent

// 以下在新版本中被屏蔽
// while (temp!=NULL)
// {
//  vDrawObject (temp->x * SNAKE_ELEMENT_SIZE, temp->y * SNAKE_ELEMENT_SIZE, &MYSPRITE);
//  temp = temp->next;
// }
// vDrawObject (snakeFood.x * SNAKE_ELEMENT_SIZE, snakeFood.y * SNAKE_ELEMENT_SIZE, &MYSPRITE);
// 在新版本中被屏蔽完毕

// while (temp!=NULL)
// {
//  vDrawObject (temp->x * SNAKE_ELEMENT_SIZE, temp->y * SNAKE_ELEMENT_SIZE, &MYSPRITE);
//  temp = temp->next;
// }
// vDrawObject (snakeFood.x * SNAKE_ELEMENT_SIZE, snakeFood.y * SNAKE_ELEMENT_SIZE, &MYSPRITE);
 // S3D
 vSetForeColor(vRGB(0,255,0));
 vDrawLine(X_MAX * SNAKE_ELEMENT_SIZE / 4 , Y_MAX  * SNAKE_ELEMENT_SIZE / 2, 0, Y_MAX * SNAKE_ELEMENT_SIZE );
 vDrawLine(X_MAX  * SNAKE_ELEMENT_SIZE / 4, Y_MAX  * SNAKE_ELEMENT_SIZE / 2, X_MAX  * SNAKE_ELEMENT_SIZE / 4, 0);
 vDrawLine(3 * X_MAX  * SNAKE_ELEMENT_SIZE / 4, Y_MAX  * SNAKE_ELEMENT_SIZE / 2, X_MAX * SNAKE_ELEMENT_SIZE , Y_MAX * SNAKE_ELEMENT_SIZE );
 vDrawLine(3 * X_MAX  * SNAKE_ELEMENT_SIZE / 4, Y_MAX  * SNAKE_ELEMENT_SIZE / 2, 3 * X_MAX * SNAKE_ELEMENT_SIZE / 4, 0);
 vDrawLine(1 * X_MAX  * SNAKE_ELEMENT_SIZE / 4, Y_MAX  * SNAKE_ELEMENT_SIZE / 2, 3 * X_MAX  * SNAKE_ELEMENT_SIZE / 4, Y_MAX  * SNAKE_ELEMENT_SIZE / 2);
 // S3DEND
 vSetForeColor(vRGB(255, 255, 255));
 while (temp != NULL)
 {
  int16_t x_0 = temp->x;
  int16_t x_1 = temp->x + 1;
  int16_t y_0 = temp->y;
  int16_t y_1 = temp->y + 1;
  
  // 首先把坐标分成标准坐标
  // 2D Test
  //x_0 = (X_MAX  / 2) * SNAKE_ELEMENT_SIZE + x_0 * SNAKE_ELEMENT_SIZE;
  //x_1 = (X_MAX  / 2) * SNAKE_ELEMENT_SIZE + x_1 * SNAKE_ELEMENT_SIZE;
  //vDrawLine(x_0, y_0, x_1, y_0);
  //vDrawLine(x_0, y_0, x_0, y_1);
  //vDrawLine(x_0, y_1, x_1, y_1);
  //vDrawLine(x_1, y_0, x_1, y_1);
  // 2D TestEND
  // S3D
  int16_t x_left_top = getS3DX(x_0, y_0);
  int16_t x_right_top = getS3DX(x_1, y_0);
  int16_t x_left_bottom = getS3DX(x_0, y_1);
  int16_t x_right_bottom = getS3DX(x_1, y_1);
  
  int16_t y_3D_0 = getS3DY(y_0);
  int16_t y_3D_1 = getS3DY(y_1);

  vDrawLine(x_left_top, y_3D_0, x_right_top, y_3D_0);
   vDrawLine(x_left_top,y_3D_0, x_left_bottom, y_3D_1);
  vDrawLine(x_left_bottom, y_3D_1, x_right_bottom, y_3D_1);
  vDrawLine(x_right_top, y_3D_0, x_right_bottom, y_3D_1);
  // S3D END


  //坐标变换
  
  temp = temp->next;
 }
 // S3D FOOD
 int16_t x_0 = snakeFood.x;
 int16_t x_1 = snakeFood.x + 1;
 int16_t y_0 = snakeFood.y;
 int16_t y_1 = snakeFood.y + 1;

 int16_t x_left_top = getS3DX(x_0, y_0);
 int16_t x_right_top = getS3DX(x_1, y_0);
 int16_t x_left_bottom = getS3DX(x_0, y_1);
 int16_t x_right_bottom = getS3DX(x_1, y_1);
  
 int16_t y_3D_0 = getS3DY(y_0);
 int16_t y_3D_1 = getS3DY(y_1);
 vSetForeColor(vRGB(255,255,0));
 vDrawLine(x_left_top, y_3D_0, x_right_top, y_3D_0);
  vDrawLine(x_left_top,y_3D_0, x_left_bottom, y_3D_1);
 vDrawLine(x_left_bottom, y_3D_1, x_right_bottom, y_3D_1);
 vDrawLine(x_right_top, y_3D_0, x_right_bottom, y_3D_1);

  // S3D FOOD END
 // 3D Backgound
 vDrawObject(1 * X_MAX  * SNAKE_ELEMENT_SIZE / 4, 0, &MY_M_SNAKE_3D_TITLE);
 // 3D Backgound END
 
 vFlipScreen(1);
}
// 销毁一切游戏中的内存碎片
void destroyObjects(void)
{
 ///////////////////////////////////////
}
int main(void)
{

 initGame();
 InitFont();
    GetScreenSize();
 initMap();
 initSnake();
 uint32_t frame;
 int16_t currentDirection = snakeHead->direction;
 while (1)
 {
  switch(vGetButtonData())
  {
  case KEY_UP:
   if (currentDirection != DOWN_DIRECTION)
   {
    snakeHead->direction = UP_DIRECTION;
   }
  break;
  case KEY_DOWN:
   if (currentDirection != UP_DIRECTION)
   {
    snakeHead->direction = DOWN_DIRECTION;
   }
  break;
  case KEY_LEFT:
   if (currentDirection != RIGHT_DIRECTION)
   {
    snakeHead->direction = LEFT_DIRECTION;
   }
  break;
  case KEY_RIGHT:
   if (currentDirection != LEFT_DIRECTION)
   {
    snakeHead->direction = RIGHT_DIRECTION;
   }
  break;
  }
  frame = vGetTickCount();
  if (counter++ > level_counter[currentLevel])
  {
   counter = 0;
   if (isTheSnakeDead != TRUE){
    moveSnake();
    currentDirection = snakeHead->direction;
   }
  }
  paintObjects();
  while (vGetTickCount() - frame < FRAME_CONTROLER);
 }
 return 0;
}

// 获得类3D的x坐标
int16_t getS3DX(int16_t x, int16_t y)
{
 int16_t result =
  (SNAKE_ELEMENT_SIZE * (X_MAX / 2))
  +
  ((x - (X_MAX / 2)) * SNAKE_ELEMENT_SIZE * ((Y_MAX + y) / 2) * SNAKE_ELEMENT_SIZE) /
  (Y_MAX * SNAKE_ELEMENT_SIZE);
 return result;
}
// 获得类3D的y坐标
int16_t getS3DY(int16_t y)
{
 return ((Y_MAX  +  y) * SNAKE_ELEMENT_SIZE) / 2;
}

图片展示:


本文地址:http://com.8s8s.com/it/it26716.htm