yl_ls
2009-03-20 15:37:38
[i=s] 本帖最后由 yl_ls 于 2009-7-22 10:10 编辑 [/i]
[url=http://www.iacger.com/]http://www.iacger.com/[/url] 首发
学了前面的教程,你是否已经想动手了呢
本例总结了前面学习的一些知识,代码比较长,最先放图了
里面游戏上有一些小的BUG,大家可以试着去修改哟
本例使用的字体在 libnge2 的 win32buildsin 目录下,包括之间的教程都应该放在此目录中运行
效果图:
[img]http://www.iacger.com/bbs/attachments/molyx/1/6/3/9/1237533805_0.jpg[/img]
资源:
[url=http://www.iacger.com/bbs/attachment.php?id=5382&u=1639&extension=wav&attach=1237533805_1.wav&filename=bump.wav&attachpath=1/6/3/9]bump.wav[/url]
[img]http://www.iacger.com/bbs/attachments/molyx/1/6/3/9/1237533805_2.png[/img]
[code=c]
#include "libnge2.h"
// 用于测试边界的常量
#define BORDERTOP 20
#define BORDERBOTTOM 252
#define BORDERLEFT 20
#define BORDERRIGHT 460
// 反击板高度常量
#define BOARDHEIGHT 40
// 退出标识
int game_quit = 0;
// 建立资源图片结构指针
image_p res;
// 建立输出文本的图片结构指针
image_p pimage_text;
// 用于显示的字体结构指针
PFont font;
// 建立音效结构指针
music_ops soundeffect;
// 保存球的状态
// 0 在左手板上准备发球
// 1 在右手板上准备发球
// 2 正在移动
int state = 0;
// 保存小球的移动量
pointf offset = {0,0};
// 分别保存左手和右手是否正按下上移或下移键
bool leftup, leftdown, rightup, rightdown;
// 保存资源图片中的四块图片的区域
rectf resrects[4] = {
{0,0,480,272}, // 背景区域
{280,0,6,40}, // 反击板区域
{279,21,25,25}, // 小球区域
{320,50,378,162} // LOGO 区域
};
// 保存两个反击板的位置
int boardleftpos = 116; // 左手反击板的位置(只保存Y轴)
int boardrightpos = 116; // 右手反击板的位置(只保存Y轴)
// 保存得分
int scoreleft = 0; // 左手得分
int scoreright = 0; // 右手得分
// 保存小球的当前位置
pointf ballpos = {20, 126};
// 按下键处理
void btn_down(int keycode)
{
switch(keycode)
{
case PSP_BUTTON_UP:
leftup = true; // 左手上移
break;
case PSP_BUTTON_DOWN:
leftdown = true; // 左手下移
break;
case PSP_BUTTON_LEFT:
break;
case PSP_BUTTON_RIGHT:
if(state==0)
{
state = 2;
offset.x = 3; // 左手发球
offset.y = -1;
}
break;
case PSP_BUTTON_TRIANGLE:
rightup = true; // 右手上移
break;
case PSP_BUTTON_CIRCLE:
break;
case PSP_BUTTON_CROSS:
rightdown = true; // 右手下移
break;
case PSP_BUTTON_SQUARE:
if(state==1)
{
state = 2;
offset.x = -3; // 右手发球
offset.y = 1;
}
break;
case PSP_BUTTON_SELECT:
game_quit = 1;
break;
case PSP_BUTTON_START:
game_quit = 1;
break;
}
}
// 释放键处理
void btn_up(int keycode)
{
switch(keycode)
{
case PSP_BUTTON_UP:
leftup = false;
break;
case PSP_BUTTON_DOWN:
leftdown = false;
break;
case PSP_BUTTON_LEFT:
break;
case PSP_BUTTON_RIGHT:
break;
case PSP_BUTTON_TRIANGLE:
rightup = false;
break;
case PSP_BUTTON_CIRCLE:
break;
case PSP_BUTTON_CROSS:
rightdown = false;
break;
case PSP_BUTTON_SQUARE:
break;
case PSP_BUTTON_SELECT:
game_quit = 1;
break;
case PSP_BUTTON_START:
game_quit = 1;
break;
}
}
// 用户绘图函数
void DrawScene()
{
// 为开始绘图准备
BeginScene(1);
// 绘制背景
DrawImage(res,
resrects[0].left,
resrects[0].top,
resrects[0].right,
resrects[0].bottom,
0, 0, 0, 0);
// 绘制小球
DrawImage(res,
resrects[2].left,
resrects[2].top,
resrects[2].right,
resrects[2].bottom,
ballpos.x, ballpos.y, 0, 0);
// 绘制反击板
DrawImage(res,
resrects[1].left,
resrects[1].top,
resrects[1].right,
resrects[1].bottom,
BORDERLEFT - 6, boardleftpos, 0, 0);
DrawImage(res,
resrects[1].left,
resrects[1].top,
resrects[1].right,
resrects[1].bottom,
BORDERRIGHT, boardrightpos, 0, 0);
// 绘制得分
DrawImage(pimage_text, 0,0,0,0,0,252,0,0);
// 完成绘图并显示
EndScene();
}
// 绘制 LOGO
void ShowLogo()
{
// 总的 LOGO 出现时间为 300/60 = 5 秒
for(int i=0;i<300;i++)
{
// 显示帧数显示
ShowFps();
// 为开始绘图准备
BeginScene(1);
if(i<51)
{
// 渐入显示 LOGO
DrawImageMask(res,
resrects[3].left,
resrects[3].top,
resrects[3].right,
resrects[3].bottom,
51,55, 0, 0, MAKE_RGBA_4444(255,255,255,i*5));
}
else if(300-i<51)
{
// 渐出显示 LOGO
DrawImageMask(res,
resrects[3].left,
resrects[3].top,
resrects[3].right,
resrects[3].bottom,
51,55, 0, 0, MAKE_RGBA_4444(255,255,255,(300-i)*5));
}
else
{
// 正常显示 LOGO
DrawImage(res,
resrects[3].left,
resrects[3].top,
resrects[3].right,
resrects[3].bottom,
51,55, 0, 0);
}
// 完成绘图并显示
EndScene();
// 限制帧数
LimitFps(60);
}
}
// 刷新得分绘制图
void UpdateScoreImage()
{
// 清除上一次绘制的文本
memset(pimage_text->data, 0, 512*32*2);
// 绘制得分
char c[8] = {0};
sprintf(c, "%4d", scoreleft);
font_drawtext(font, c ,strlen(c), pimage_text, 2, 2, FONT_SHOW_SHADOW);
sprintf(c, "%4d", scoreright);
font_drawtext(font, c ,strlen(c), pimage_text, 400, 2, FONT_SHOW_SHADOW);
}
// 处理游戏中的变量和更新状态
void GameProc()
{
// 处理反击板移动
if(leftup != leftdown)
{
if(leftup)
{
if(boardleftpos > BORDERTOP)
{
boardleftpos--;
}
}
else
{
if(boardleftpos + BOARDHEIGHT < BORDERBOTTOM)
{
boardleftpos++;
}
}
}
if(rightup != rightdown)
{
if(rightup)
{
if(boardrightpos > BORDERTOP)
{
boardrightpos--;
}
}
else
{
if(boardrightpos + BOARDHEIGHT < BORDERBOTTOM)
{
boardrightpos++;
}
}
}
// 处理小球移动
switch(state)
{
case 0:
// 小球随左板移动
ballpos.x = BORDERLEFT;
ballpos.y = boardleftpos + BOARDHEIGHT / 2 - 10;
break;
case 1:
// 小球随右板移动
ballpos.x = BORDERRIGHT - 20;
ballpos.y = boardrightpos + BOARDHEIGHT / 2 - 10;
break;
default:
// 小球正常移动
// 处理上下反弹
if(offset.y != 0)
{
if(offset.y > 0)
{
// 向下移动中
if(ballpos.y + offset.y + 20 >= BORDERBOTTOM)
{
// 计算反弹新位置
ballpos.y -= (ballpos.y + offset.x + 20 - BORDERBOTTOM);
offset.y = -offset.y;
// 播放音效
soundeffect.playstop();
}
else
{
ballpos.y += offset.y;
}
}
else
{
// 向上移动中
if(ballpos.y + offset.y <= BORDERTOP)
{
// 计算反弹新位置
float hotposyp = ballpos.y - BORDERTOP;
float hotposx = ballpos.x + (offset.x/offset.y) * hotposyp;
ballpos.y = BORDERTOP + hotposyp;
ballpos.x = hotposx;
offset.y = -offset.y;
// 播放音效
soundeffect.playstop();
}
else
{
ballpos.y += offset.y;
}
}
}
if(offset.x != 0)
{
if(offset.x > 0)
{
if(ballpos.x >= 480)
{
// 小球从右边出界了
state = 1;
scoreleft++;
UpdateScoreImage();
}
// 向右移动中
if(ballpos.x + offset.x + 20 >= BORDERRIGHT)
{
// 计算可能的反弹点
float hotposxp = BORDERRIGHT - ballpos.x - 20;
float hotposy = ballpos.y + (offset.y/offset.x) * hotposxp;
// 到右边界,计算右板是否可以反弹
if(hotposy + 10 > boardrightpos && hotposy + 10 < boardrightpos + BOARDHEIGHT)
{
ballpos.x -= (hotposxp - offset.x);
offset.x = -offset.x;
// 播放音效
soundeffect.playstop();
}
else
{
ballpos.x += offset.x;
}
}
else
{
ballpos.x += offset.x;
}
}
else
{
if(ballpos.x - 20 <= 0)
{
// 小球从左边出界了
state = 0;
scoreright++;
UpdateScoreImage();
}
// 向左移动
if(ballpos.x + offset.x <= BORDERLEFT)
{
// 计算可能的反弹点
float hotposxp = ballpos.x - BORDERLEFT;
float hotposy = ballpos.y - (offset.y/offset.x) * hotposxp;
// 到左边界,计算右板是否可以反弹
if(hotposy + 10 > boardleftpos && hotposy + 10 < boardleftpos + BOARDHEIGHT)
{
ballpos.x -= (hotposxp - offset.x);
offset.x = -offset.x;
// 播放音效
soundeffect.playstop();
}
else
{
ballpos.x += offset.x;
}
}
else
{
ballpos.x += offset.x;
}
}
}
break;
}
}
extern "C"
int main(int argc, char* argv[])
{
// nge 初始化
NGE_Init(INIT_ALL);
// 加载资源图片
res = image_load("images/res.png", DISPLAY_PIXEL_FORMAT_4444, 1);
// 建立用于显示文本的图片
pimage_text = image_create(480, 20, DISPLAY_PIXEL_FORMAT_4444);
// 加载字体
font = create_font_hzk("fonts/GBK16", "fonts/ASC16", 16, DISPLAY_PIXEL_FORMAT_4444);
// 设置白色
font_setcolor(font, MAKE_RGBA_4444(255,255,255,255));
// 加载音效
PCMPlayInit(&soundeffect);
soundeffect.load("music/bump.wav");
// 调用绘制 LOGO 的函数
ShowLogo();
UpdateScoreImage();
// 设置自定义按钮处理函数
InitInput(btn_down,btn_up,1);
while ( !game_quit )
{
// 显示帧数显示
ShowFps();
// 要求 nge2 处理按键,它将使用 InitInput 定义的函数来处理
InputProc();
// 调用用户游戏处理函数
GameProc();
// 调用用户绘图函数
DrawScene();
// 限制帧数
LimitFps(60);
}
PCMPlayFini();
// 释放字体
font_destory(font);
// 释放资源图片
image_free(res);
// nge 退出处理
NGE_Quit();
return 0;
}
[/code]
lihuaning
2009-07-22 03:44:31
楼猪,图挂了。。。修复吧,话说真深奥哦。。。
yl_ls
2009-07-22 10:11:03
图已修复~~~~~~,其实不太难,不过最好按教程顺序来看
huijuan520
2010-10-22 02:48:44
够我们新手看好久的了