我实现了下面的Tron循环游戏,以便它可以在GameCube / Wii设备上运行(隔离.)。事实上,有很多工具(我依赖于devkitPPC),我认为Tron游戏对于这种开发来说是一个简单的起点。
我没有C方面的经验,也没有在C中执行“类”的经验,也没有在游戏开发方面的经验(命名可能很可怕),因此,任何帮助都将受到欢迎!
目录结构如下:
├── Makefile
├── source
│ └── tron.c
└── textures
├── ballsprites.png
└── textures.scf下面列出了不同的文件(我编写的唯一文件是tron.c和精灵,其余的都归功于devkit后面的团队!)
Wall walls[NUM_PLAYERS][NUM_WALLS];是一个全局变量,而不是VersusEngineManager类的属性,因为模拟器总是触发奇怪的内存错误。在这一点上的任何帮助都会很棒!
文本.
tron.c
#include
#include
#include
#include
#include
#include
#include
#include "textures_tpl.h"
#include "textures.h"
#define DEFAULT_FIFO_SIZE (256*1024)
static void *frameBuffer[2] = { NULL, NULL};
static GXRModeObj *rmode;
#define NUM_PLAYERS 2
#define NUM_WALLS 20000
#define SPEED 0x200
#define SPRITE_SIZE 4
#define WIDTH 640
#define HEIGHT 480
#define UPPER_MARGIN 20
#define TV_MARGIN 50
typedef struct
{
int x, y;
} Point;
bool Point_CheckInRectangle(Point *self, int xmin, int xmax, int ymin, int ymax);
bool Point_CheckCollision(Point *self, Point *other);
typedef struct
{
int x, y;
int dx, dy;
int image;
} Player;
int Player_init(Player *self, int x, int y, int dx, int dy, int image);
void Player_UpdatePosition(Player *self);
typedef struct
{
int x, y;
int image;
} Wall;
int playerLossesCount[NUM_PLAYERS];
Wall walls[NUM_PLAYERS][NUM_WALLS];
typedef struct
{
int speed;
int nPlayers;
int wallIndex;
Player players[NUM_PLAYERS];
} VersusEngineManager;
int VersusEngineManager_init(VersusEngineManager *self, int speed, int nPlayers);
bool VersusEngineManager_CheckPlayersCollision(VersusEngineManager *self);
bool VersusEngineManager_CheckWallCollision(VersusEngineManager *self, int playerId);
int VersusEngineManager_UpdateGameState(VersusEngineManager *self);
void VersusEngineManager_UpdatePlayerDirectionFromPAD(VersusEngineManager *self, int pad, int playerId);
void VersusEngineManager_UpdatePlayersDirectionFromPADs(VersusEngineManager *self);
void VersusEngineManager_UpdatePlayersDirectionFromPADs(VersusEngineManager *self)
{
VersusEngineManager_UpdatePlayerDirectionFromPAD(self, 0, 0);
VersusEngineManager_UpdatePlayerDirectionFromPAD(self, 1, 1);
}
typedef struct
{
int spriteSize;
} SpriteDrawer;
int SpriteDrawer_init(SpriteDrawer *self, int spriteSize);
void SpriteDrawer_Rectangle(SpriteDrawer *self, int x, int y, int width, int height, int image);
void SpriteDrawer_SpriteTex(SpriteDrawer *self, int x, int y, int width, int height, int image);
void SpriteDrawer_AllSprites(SpriteDrawer *self);
void SpriteDrawer_Sprites(SpriteDrawer *self, VersusEngineManager *versusEngineManager);
void SpriteDrawer_Scores(SpriteDrawer *self, VersusEngineManager *versusEngineManager);
void SpriteDrawer_ArenaSprites(SpriteDrawer *self);
GXTexObj texObj;
int main( int argc, char **argv ){
u32 fb; // initial framebuffer index
u32 first_frame;
f32 yscale;
u32 xfbHeight;
Mtx44 perspective;
Mtx GXmodelView2D;
void *gp_fifo = NULL;
GXColor background = {0, 0, 0, 0xff};
VIDEO_Init();
rmode = VIDEO_GetPreferredMode(NULL);
fb = 0;
first_frame = 1;
// allocate 2 framebuffers for double buffering
frameBuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
frameBuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
fb ^= 1;
// setup the fifo and then init the flipper
gp_fifo = memalign(32,DEFAULT_FIFO_SIZE);
memset(gp_fifo,0,DEFAULT_FIFO_SIZE);
GX_Init(gp_fifo,DEFAULT_FIFO_SIZE);
// clears the bg to color and clears the z buffer
GX_SetCopyClear(background, 0x00ffffff);
// other gx setup
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight);
xfbHeight = GX_SetDispCopyYScale(yscale);
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
GX_SetDispCopyDst(rmode->fbWidth,xfbHeight);
GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter);
GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
if (rmode->aa)
GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
else
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
GX_SetCullMode(GX_CULL_NONE);
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
GX_SetDispCopyGamma(GX_GM_1_0);
// setup the vertex descriptor
// tells the flipper to expect direct data
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetNumChans(1);
GX_SetNumTexGens(1);
GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GX_InvalidateTexAll();
TPLFile spriteTPL;
TPL_OpenTPLFromMemory(&spriteTPL, (void *)textures_tpl,textures_tpl_size);
TPL_GetTexture(&spriteTPL,ballsprites,&texObj);
GX_LoadTexObj(&texObj, GX_TEXMAP0);
guOrtho(perspective,0,479,0,639,0,300);
GX_LoadProjectionMtx(perspective, GX_ORTHOGRAPHIC);
PAD_Init();
srand(time(NULL));
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
guMtxIdentity(GXmodelView2D);
guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -5.0F);
GX_LoadPosMtxImm(GXmodelView2D,GX_PNMTX0);
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
GX_SetAlphaUpdate(GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
VersusEngineManager versusEngineManager;
VersusEngineManager_init(&versusEngineManager, SPEED, NUM_PLAYERS);
SpriteDrawer spriteDrawer;
SpriteDrawer_init(&spriteDrawer, SPRITE_SIZE);
while(1) {
GX_InvVtxCache();
GX_InvalidateTexAll();
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
VersusEngineManager_UpdatePlayersDirectionFromPADs(&versusEngineManager);
int gameState = VersusEngineManager_UpdateGameState(&versusEngineManager);
if(gameState==1) { VersusEngineManager_init(&versusEngineManager, SPEED, NUM_PLAYERS); }
SpriteDrawer_Sprites(&spriteDrawer, &versusEngineManager);
GX_DrawDone();
GX_CopyDisp(frameBuffer[fb],GX_TRUE);
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
if(first_frame) {
VIDEO_SetBlack(FALSE);
first_frame = 0;
}
VIDEO_Flush();
VIDEO_WaitVSync();
fb ^= 1; // flip framebuffer
}
return 0;
}
float texCoords[] = {
0.0 ,0.0 , 0.5, 0.0, 0.5, 0.5, 0.0, 0.5,
0.5 ,0.0 , 1.0, 0.0, 1.0, 0.5, 0.5, 0.5,
0.0 ,0.5 , 0.5, 0.5, 0.5, 1.0, 0.0, 1.0,
0.5 ,0.5 , 1.0, 0.5, 1.0, 1.0, 0.5, 1.0
};
int SpriteDrawer_init(SpriteDrawer *self, int spriteSize)
{
self->spriteSize = spriteSize;
return 0;
}
void SpriteDrawer_Sprites(SpriteDrawer *self, VersusEngineManager *versusEngineManager) {
int spriteSize = self->spriteSize;
for(int playerId=0;playerIdplayers[playerId].x >> 8,
versusEngineManager->players[playerId].y >> 8,
spriteSize,
spriteSize,
versusEngineManager->players[playerId].image);
for(int wallId=0; wallId < NUM_WALLS; wallId++) {
SpriteDrawer_SpriteTex(self,
walls[playerId][wallId].x >> 8,
walls[playerId][wallId].y >> 8,
spriteSize,
spriteSize,
walls[playerId][wallId].image);
}
}
SpriteDrawer_ArenaSprites(self);
SpriteDrawer_Scores(self, versusEngineManager);
};
void SpriteDrawer_ArenaSprites(SpriteDrawer *self) {
int spriteSize = self->spriteSize;
SpriteDrawer_Rectangle(self, TV_MARGIN,UPPER_MARGIN+TV_MARGIN, WIDTH-2*TV_MARGIN-spriteSize, HEIGHT - 2*TV_MARGIN - spriteSize,3);
};
void SpriteDrawer_Rectangle(SpriteDrawer *self, int x,int y,int width,int height,int sprite) {
int spriteSize = self->spriteSize;
for(int i=x; i < x+width;i+=spriteSize){
SpriteDrawer_SpriteTex(self, i,y,spriteSize, spriteSize, sprite);
}
for(int i=x; i < x+width+spriteSize;i+=spriteSize){
SpriteDrawer_SpriteTex(self, i,y+height,spriteSize, spriteSize, sprite);
}
for(int i=y; i < y+height;i+=spriteSize){
SpriteDrawer_SpriteTex(self, x,i,spriteSize, spriteSize, sprite);
}
for(int i=y; i < y+height;i+=spriteSize){
SpriteDrawer_SpriteTex(self, x+width,i,spriteSize, spriteSize, sprite);
}
};
void SpriteDrawer_Scores(SpriteDrawer *self, VersusEngineManager *versusEngineManager) {
int spriteSize = self->spriteSize;
for(int playerId=0;playerId> 8), TV_MARGIN + 2* SPEED * (1 + playerId) >> 8, spriteSize, spriteSize, versusEngineManager->players[playerId].image);
}
}
};
void SpriteDrawer_SpriteTex(SpriteDrawer *self, int x, int y, int width, int height, int image ) {
int texIndex = image * 8;
GX_Begin(GX_QUADS, GX_VTXFMT0, 4); // Draw A Quad
GX_Position2f32(x, y); // Top Left
GX_TexCoord2f32(texCoords[texIndex],texCoords[texIndex+1]);
texIndex+=2;
GX_Position2f32(x+width-1, y); // Top Right
GX_TexCoord2f32(texCoords[texIndex],texCoords[texIndex+1]);
texIndex+=2;
GX_Position2f32(x+width-1,y+height-1); // Bottom Right
GX_TexCoord2f32(texCoords[texIndex],texCoords[texIndex+1]);
texIndex+=2;
GX_Position2f32(x,y+height-1); // Bottom Left
GX_TexCoord2f32(texCoords[texIndex],texCoords[texIndex+1]);
GX_End(); // Done Drawing The Quad
}
int Player_init(Player *self, int x, int y, int dx, int dy, int image)
{
self->x = x;
self->y = y;
self->dx = dx;
self->dy = dy;
self->image = image;
return 0;
}
void Player_UpdatePosition(Player *self)
{
self->x += self->dx;
self->y += self->dy;
}
bool Point_CheckInRectangle(Point *self, int xmin, int xmax, int ymin, int ymax)
{
return self->x < xmin || self->x > xmax || self->y < ymin || self->y > ymax;
}
bool Point_CheckCollision(Point *self, Point *other)
{
return self->x == other->x && self->y==other->y;
}
int VersusEngineManager_init(VersusEngineManager *self, int speed, int nPlayers)
{
self->speed = speed;
self->nPlayers = nPlayers;
self->wallIndex = 0;
Player player0, player1;
Player_init(&player0, ((WIDTH - SPRITE_SIZE ) / 2 ) << 8,100 << 8,0, SPEED, 0);
Player_init(&player1, ((WIDTH - SPRITE_SIZE ) / 2 ) << 8,400 << 8,0, -SPEED, 1);
self->players[0] = player0;
self->players[1] = player1;
for(int playerId=0;playerIdnPlayers;playerId++){
for(int wallId=0; wallId < NUM_WALLS; wallId++) {
walls[playerId][wallId].x = 0;
walls[playerId][wallId].y = 0;
walls[playerId][wallId].image = 2;
}
}
return 0;
}
bool VersusEngineManager_CheckPlayersCollision(VersusEngineManager *self)
{
for(int i=0; i < self->nPlayers; i++)
{
for(int j=i+1; j < self->nPlayers; j++)
{
if(Point_CheckCollision(&self->players[i], &self->players[j]) ) {
return true; }
}
}
return false;
};
bool VersusEngineManager_CheckWallCollision(VersusEngineManager *self, int playerId)
{
if(Point_CheckInRectangle(&self->players[playerId],
TV_MARGIN<<8,
WIDTH-SPRITE_SIZE-TV_MARGIN << 8,
(UPPER_MARGIN + TV_MARGIN) <<8 ,
(HEIGHT+UPPER_MARGIN-SPRITE_SIZE-TV_MARGIN) << 8))
{return true;}
for(int i=0;iwallIndex; wallId++) {
if(self->players[playerId].x == walls[i][wallId].x && self->players[playerId].y == walls[i][wallId].y) {
return true;
}
}
}
return false;
}
int VersusEngineManager_UpdateGameState(VersusEngineManager *self)
{
for(int playerId=0;playerIdnPlayers;playerId++){
Player_UpdatePosition(&self->players[playerId]);
bool collision = false;
if (VersusEngineManager_CheckPlayersCollision(self)) {
collision = true;
}
else if(VersusEngineManager_CheckWallCollision(self, playerId)) {
playerLossesCount[playerId] += 1;
collision = true;
}
walls[playerId][self->wallIndex].x = self->players[playerId].x;
walls[playerId][self->wallIndex].y = self->players[playerId].y;
walls[playerId][self->wallIndex].image = playerId;
if(collision) {return 1;} ;
}
self->wallIndex += 1;
return 0;
};
void VersusEngineManager_UpdatePlayerDirectionFromPAD(VersusEngineManager *self, int pad, int playerId)
{
PAD_ScanPads();
if (PAD_ButtonsDown(pad) & PAD_BUTTON_LEFT) {
if (self->players[playerId].dx ==0) {
self->players[playerId].dx = -self->speed;
self->players[playerId].dy = 0;
return;
}
}
if (PAD_ButtonsDown(pad) & PAD_BUTTON_RIGHT) {
if (self->players[playerId].dx ==0) {
self->players[playerId].dx = self->speed;
self->players[playerId].dy = 0;
return;
}
}
if (PAD_ButtonsDown(pad) & PAD_BUTTON_UP) {
if (self->players[playerId].dy ==0) {
self->players[playerId].dx = 0;
self->players[playerId].dy = -self->speed;
return;
}
}
if (PAD_ButtonsDown(pad) & PAD_BUTTON_DOWN) {
if (self->players[playerId].dy ==0) {
self->players[playerId].dx = 0;
self->players[playerId].dy = self->speed;
return;
}
}
}Makefile
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
.SECONDARY:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC")
endif
include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA :=
TEXTURES := textures
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -logc -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(foreach dir,$(TEXTURES),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
SCFFILES := $(foreach dir,$(TEXTURES),$(notdir $(wildcard $(dir)/*.scf)))
TPLFILES := $(SCFFILES:.scf=.tpl)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
export OFILES_BIN := $(addsuffix .o,$(BINFILES)) $(addsuffix .o,$(TPLFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(addsuffix .h,$(subst .,_,$(TPLFILES)))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
$(OFILES_SOURCES) : $(HFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .bin extension
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.tpl.o %_tpl.h : %.tpl
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPSDIR)/*.d
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------<#>球棒.

发布于 2020-03-23 16:36:23
C中没有类,但是有函数。
关于:
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) 编译时,始终启用警告,然后修复这些警告。(对于gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11 )
每次引用该宏时,=都会使其重新评估.建议:
CFLAGS := -g -O2 -Wall $(MACHDEP) $(INCLUDE) 注意:=而不是=
声明的结构不被指定为tag名称。当使用调试器时,这将成为一个问题,因为大多数调试器都需要一个标记名才能显示结构中的各个字段。
发布于 2020-03-22 14:46:27
您有一个文件程序,所以更多的方法和全局,包括:
int playerLossesCount[NUM_PLAYERS];
Wall walls[NUM_PLAYERS][NUM_WALLS];
GXTexObj texObj;应该是static。
变量的
int main( int argc, char **argv ){
u32 fb; // initial framebuffer index
u32 first_frame;
f32 yscale;
u32 xfbHeight;
Mtx44 perspective;
Mtx GXmodelView2D;
void *gp_fifo = NULL;这种风格是典型的前C99代码,但通常情况下,它更难遵循这样的代码。如果这些变量是在离实际使用的地方更近的地方声明和初始化的,就更容易辨认了。
对于空格,C通常比Python更自由,但如下所示:
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);还需要更多。可能每个逗号后面有一个空格,这样才能看得清楚。同时,你的支撑风格也有很大的差异;比较一下
if(Point_CheckCollision(&self->players[i], &self->players[j]) ) {
return true; }使用
if(Point_CheckInRectangle(&self->players[playerId],
TV_MARGIN<<8,
WIDTH-SPRITE_SIZE-TV_MARGIN << 8,
(UPPER_MARGIN + TV_MARGIN) <<8 ,
(HEIGHT+UPPER_MARGIN-SPRITE_SIZE-TV_MARGIN) << 8))
{return true;}使用
if(self->players[playerId].x == walls[i][wallId].x && self->players[playerId].y == walls[i][wallId].y) {
return true;
} 最后一个似乎是最理智的,但无论你做什么,选择一种风格,并坚持它。
基于对此的解读:
float texCoords[] = {
0.0 ,0.0 , 0.5, 0.0, 0.5, 0.5, 0.0, 0.5,
// ...
GX_TexCoord2f32(texCoords[texIndex],texCoords[texIndex+1]);好像你在把一个坐标数组压平,表示为x,y,x,y.如果要使用一个Point结构数组(您甚至自己声明了一个;您也可以使用它),那么您的代码会更容易读懂。
这是:
for(int i=y; i < y+height;i+=spriteSize){
SpriteDrawer_SpriteTex(self, x,i,spriteSize, spriteSize, sprite);
}
for(int i=y; i < y+height;i+=spriteSize){
SpriteDrawer_SpriteTex(self, x+width,i,spriteSize, spriteSize, sprite);
}应该成为等价物
for(int i=y; i < y+height;i+=spriteSize){
SpriteDrawer_SpriteTex(self, x,i,spriteSize, spriteSize, sprite);
SpriteDrawer_SpriteTex(self, x+width,i,spriteSize, spriteSize, sprite);
}https://codereview.stackexchange.com/questions/239272
复制相似问题