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