SGL图形库是为Windows图形界面编程服务的,而且一切都是考虑到对新手友好的。在具体介绍提供给用户的函数之前,需要先说明一下应该以什么样的思路来构思我们的SGL程序。
作为C语言程序,main函数总是需要在最开始就了解一下的。在SGL库中,可以将main理解为
void main(){
sgSetup();
while(1){
sgLoop();
}
}
其中sgSetup函数和sgLoop函数都是需要由用户来完成的,也就是说我们负责初始化我们的SGL程序然后完成其中的循环逻辑就可以了。其根本思路就是,setup函数里设置与窗口鼠标键盘有关的属性,loop函数绘制每一帧的图案。所以,SGL程序是不会自动结束的,要结束程序的话,可以调用exit(0)这样的函数来实现。
至于loop函数里的逻辑该怎么实现,有两种方法。举个抽象点的例子,比如y = x的平方,我们要依次求出x为1,2,3…的y值,我们既可以每次直接计算x的平方,也可以根据上一次计算的y’来计算当前的y = y’ + 2*x - 1。那么这两种思路也可以应用到我们的SGL程序中。我们既可以直接算出每次loop中需要计算的变量,也可以根据上一次loop的结果进行迭代。两种方法的主要区别在于效率,需要具体情况具体分析。
下面给大家贴一个用SGL实现的简单小游戏,可以简单了解一下程序的结构,里面函数的具体用法后续文章会讨论。
#include "winsgl.h"
#define inRect(x, y, x1, y1, x2, y2) ((x>=x1&&x<=x2)&&(y>=y1&&y<=y2))
#define speedUp(e) (e+=e>0?2:-2)
void movePlayer(int x, int y);
void moveEnemy();
int hasCollision();
struct _player {
vecTwo pos;
bitMap *oldImage;
}player;
struct _enemy {
vecTwo pos;
vecTwo vel;
bitMap *oldImage;
}enemy1, enemy2, enemy3, enemy4;
int liveTime = 0;
void sgSetup() {
initWindow(640, 640, "Collision --SGL Sample Game", BIT_MAP);
initMouse(SG_COORDINATE);
player.oldImage = (bitMap*)malloc(sizeof(bitMap));
enemy1.oldImage = (bitMap*)malloc(sizeof(bitMap));
enemy2.oldImage = (bitMap*)malloc(sizeof(bitMap));
enemy3.oldImage = (bitMap*)malloc(sizeof(bitMap));
enemy4.oldImage = (bitMap*)malloc(sizeof(bitMap));
}
void sgLoop() {
static int first = 1, cont = 0, drag = 0;
vecTwo position;
int press;
if (first) {
loadBmp(0, 0, "Source\\collision\\background.bmp");
player.pos.x = player.pos.y = 290;
enemy1.pos.x = 120;
enemy1.pos.y = 100;
enemy2.pos.x = 432;
enemy2.pos.y = 120;
enemy3.pos.x = 100;
enemy3.pos.y = 432;
enemy4.pos.x = 480;
enemy4.pos.y = 480;
enemy1.vel.x = enemy1.vel.y = enemy2.vel.y = enemy3.vel.x = 4;
enemy4.vel.x = enemy4.vel.y = enemy3.vel.y = enemy2.vel.x = -4;
getImage(player.pos.x, player.pos.y, player.pos.x + 59, player.pos.y + 59, player.oldImage);
getImage(enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63, enemy1.oldImage);
getImage(enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31, enemy2.oldImage);
getImage(enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95, enemy3.oldImage);
getImage(enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51, enemy4.oldImage);
setColor(255, 0, 0);
putQuad(player.pos.x, player.pos.y, player.pos.x + 59, player.pos.y + 59, SOLID_FILL);
setColor(0, 0, 255);
putQuad(enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63, SOLID_FILL);
putQuad(enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31, SOLID_FILL);
putQuad(enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95, SOLID_FILL);
putQuad(enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51, SOLID_FILL);
first = 0;
}
press = mouseStatus(SG_LEFT_BUTTON);
position = mousePos();
setColor(0, 0, 0);
putQuad(0, 0, 639, 39, SOLID_FILL);
setColor(255, 255, 0);
putNumber(liveTime, 640, 0, 'r');
if (hasCollision()) {
first = 1;
cont = 0;
drag = 0;
return;
}
if (press==SG_BUTTON_DOWN&&(inRect(position.x, position.y, player.pos.x, player.pos.y, player.pos.x+59, player.pos.y+59)||drag)) {
if(!cont)liveTime = 0;
cont = drag = 1;
movePlayer(position.x - 29, position.y - 29);
}
if (press == SG_BUTTON_UP && inRect(position.x, position.y, player.pos.x, player.pos.y, player.pos.x + 59, player.pos.y + 59))drag = 0;
if (!cont)return;
else {
moveEnemy();
delayEnd(20);
delayBegin();
liveTime += 24;
}
}
void movePlayer(int x, int y) {
putImage(player.pos.x, player.pos.y, player.oldImage, COPY_PUT);
setColor(255, 0, 0);
player.pos.x = x;
player.pos.y = y;
free(player.oldImage->data);
getImage(player.pos.x, player.pos.y, player.pos.x + 83, player.pos.y + 63, player.oldImage);
putQuad(player.pos.x, player.pos.y, player.pos.x + 59, player.pos.y + 59, SOLID_FILL);
}
void moveEnemy() {
putImage(enemy1.pos.x, enemy1.pos.y, enemy1.oldImage, COPY_PUT);
putImage(enemy2.pos.x, enemy2.pos.y, enemy2.oldImage, COPY_PUT);
putImage(enemy3.pos.x, enemy3.pos.y, enemy3.oldImage, COPY_PUT);
putImage(enemy4.pos.x, enemy4.pos.y, enemy4.oldImage, COPY_PUT);
if (liveTime % 10000 < 24) {
speedUp(enemy1.vel.x);
speedUp(enemy1.vel.y);
speedUp(enemy2.vel.x);
speedUp(enemy2.vel.y);
speedUp(enemy3.vel.x);
speedUp(enemy3.vel.y);
speedUp(enemy4.vel.x);
speedUp(enemy4.vel.y);
}
enemy1.pos.x += enemy1.vel.x;
enemy1.pos.y += enemy1.vel.y;
enemy2.pos.x += enemy2.vel.x;
enemy2.pos.y += enemy2.vel.y;
enemy3.pos.x += enemy3.vel.x;
enemy3.pos.y += enemy3.vel.y;
enemy4.pos.x += enemy4.vel.x;
enemy4.pos.y += enemy4.vel.y;
if (enemy1.pos.x < 0) {
enemy1.pos.x = -enemy1.pos.x;
enemy1.vel.x = -enemy1.vel.x;
}
if (enemy1.pos.x > 555) {
enemy1.pos.x = 1110-enemy1.pos.x;
enemy1.vel.x = -enemy1.vel.x;
}
if (enemy1.pos.y < 0) {
enemy1.pos.y = -enemy1.pos.y;
enemy1.vel.y = -enemy1.vel.y;
}
if (enemy1.pos.y > 575) {
enemy1.pos.y = 1150 - enemy1.pos.y;
enemy1.vel.y = -enemy1.vel.y;
}
if (enemy2.pos.x < 0) {
enemy2.pos.x = -enemy2.pos.x;
enemy2.vel.x = -enemy2.vel.x;
}
if (enemy2.pos.x > 503) {
enemy2.pos.x = 1006 - enemy2.pos.x;
enemy2.vel.x = -enemy2.vel.x;
}
if (enemy2.pos.y < 0) {
enemy2.pos.y = -enemy2.pos.y;
enemy2.vel.y = -enemy2.vel.y;
}
if (enemy2.pos.y > 607) {
enemy2.pos.y = 1214 - enemy2.pos.y;
enemy2.vel.y = -enemy2.vel.y;
}
if (enemy3.pos.x < 0) {
enemy3.pos.x = -enemy3.pos.x;
enemy3.vel.x = -enemy3.vel.x;
}
if (enemy3.pos.x > 579) {
enemy3.pos.x = 1158 - enemy3.pos.x;
enemy3.vel.x = -enemy3.vel.x;
}
if (enemy3.pos.y < 0) {
enemy3.pos.y = -enemy3.pos.y;
enemy3.vel.y = -enemy3.vel.y;
}
if (enemy3.pos.y > 543) {
enemy3.pos.y = 1086 - enemy3.pos.y;
enemy3.vel.y = -enemy3.vel.y;
}
if (enemy4.pos.x < 0) {
enemy4.pos.x = -enemy4.pos.x;
enemy4.vel.x = -enemy4.vel.x;
}
if (enemy4.pos.x > 575) {
enemy4.pos.x = 1150 - enemy4.pos.x;
enemy4.vel.x = -enemy4.vel.x;
}
if (enemy4.pos.y < 0) {
enemy4.pos.y = -enemy4.pos.y;
enemy4.vel.y = -enemy4.vel.y;
}
if (enemy4.pos.y > 588) {
enemy4.pos.y = 1176 - enemy4.pos.y;
enemy4.vel.y = -enemy4.vel.y;
}
free(enemy1.oldImage->data);
free(enemy2.oldImage->data);
free(enemy3.oldImage->data);
free(enemy4.oldImage->data);
getImage(enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63, enemy1.oldImage);
getImage(enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31, enemy2.oldImage);
getImage(enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95, enemy3.oldImage);
getImage(enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51, enemy4.oldImage);
setColor(0, 0, 255);
putQuad(enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63, SOLID_FILL);
putQuad(enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31, SOLID_FILL);
putQuad(enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95, SOLID_FILL);
putQuad(enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51, SOLID_FILL);
}
int hasCollision() {
if (inRect(player.pos.x, player.pos.y, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x, player.pos.y + 29, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x, player.pos.y + 59, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x + 29, player.pos.y, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x + 29, player.pos.y + 59, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x + 59, player.pos.y, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 29, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 59, enemy1.pos.x, enemy1.pos.y, enemy1.pos.x + 83, enemy1.pos.y + 63))return 1;
if (inRect(player.pos.x, player.pos.y, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x, player.pos.y + 29, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x, player.pos.y + 59, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x + 29, player.pos.y, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x + 29, player.pos.y + 59, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x + 59, player.pos.y, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 29, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 59, enemy2.pos.x, enemy2.pos.y, enemy2.pos.x + 135, enemy2.pos.y + 31))return 1;
if (inRect(player.pos.x, player.pos.y, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x, player.pos.y + 29, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x, player.pos.y + 59, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x + 29, player.pos.y, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x + 29, player.pos.y + 59, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x + 59, player.pos.y, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 29, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 59, enemy3.pos.x, enemy3.pos.y, enemy3.pos.x + 59, enemy3.pos.y + 95))return 1;
if (inRect(player.pos.x, player.pos.y, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x, player.pos.y + 29, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x, player.pos.y + 59, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x + 29, player.pos.y, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x + 29, player.pos.y + 59, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x + 59, player.pos.y, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 29, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (inRect(player.pos.x + 59, player.pos.y + 59, enemy4.pos.x, enemy4.pos.y, enemy4.pos.x + 63, enemy4.pos.y + 51))return 1;
if (!inRect(player.pos.x, player.pos.y, 40, 40, 539, 539))return 1;
return 0;
}
代码是很久很久之前写的了,看起来冗余程度很高,不过我也懒得优化了。
里面用到的背景图片我上传了,可以根据自己的审美p图,让这个程序看起来好看一点。需要注意的一点就是四周那个黑框是有作用的,需要保留,中间的空白可以换成自己喜欢的图片。但是,我没换过背景图片,不保证没有bug。