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; }
图片展示:


|