diff --git a/samples/pong/Makefile b/samples/pong/Makefile new file mode 100644 index 0000000..3c0b7e8 --- /dev/null +++ b/samples/pong/Makefile @@ -0,0 +1,70 @@ +.SUFFIXES: + +ifeq ($(strip $(WUT_ROOT)),) +$(error "Please ensure WUT_ROOT is in your environment.") +endif + +ifeq ($(shell uname -o),Cygwin) +ROOT := $(shell cygpath -w ${CURDIR}) +WUT_ROOT := $(shell cygpath -w ${WUT_ROOT}) +else +ROOT := $(CURDIR) +endif + +include $(WUT_ROOT)/rules/rpl.mk + +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCE := src +INCLUDE := include +DATA := data +LIBS := -lgcc -lcrt -lcoreinit -lvpad -lsysapp + +CFLAGS += -O2 -Wall -std=c11 +CXXFLAGS += -O2 -Wall +ASFLAGS += -mregnames + +ifneq ($(BUILD),$(notdir $(CURDIR))) + +export OUTPUT := $(ROOT)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCE),$(ROOT)/$(dir)) \ + $(foreach dir,$(DATA),$(ROOT)/$(dir)) +export BUILDDIR := $(ROOT) +export DEPSDIR := $(BUILDDIR) + +CFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.c))) +CXXFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCE),$(notdir $(wildcard $(dir)/*.S))) + +ifeq ($(strip $(CXXFILES)),) +export LD := $(CC) +else +export LD := $(CXX) +endif + +export OFILES := $(CFILES:.c=.o) \ + $(CXXFILES:.cpp=.o) \ + $(SFILES:.S=.o) +export INCLUDES := $(foreach dir,$(INCLUDE),-I$(ROOT)/$(dir)) \ + -I$(ROOT)/$(BUILD) + +.PHONY: $(BUILD) clean + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(ROOT)/Makefile + +clean: + @echo "[RM] $(notdir $(OUTPUT))" + @rm -rf $(BUILD) $(OUTPUT).elf $(OUTPUT).rpx $(OUTPUT).a + +else + +DEPENDS := $(OFILES:.o=.d) + +$(OUTPUT).rpx: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +-include $(DEPENDS) + +endif diff --git a/samples/pong/src/draw.c b/samples/pong/src/draw.c new file mode 100755 index 0000000..113557f --- /dev/null +++ b/samples/pong/src/draw.c @@ -0,0 +1,176 @@ +#include "draw.h" + +#include +#include + +void *screenBuffer; + +void flipBuffers() +{ + //Grab the buffer size for each screen (TV and gamepad) + int buf0_size = OSScreenGetBufferSizeEx(0); + int buf1_size = OSScreenGetBufferSizeEx(1); + + //Flush the cache + DCFlushRange((void *)screenBuffer + buf0_size, buf1_size); + DCFlushRange((void *)screenBuffer, buf0_size); + + //Flip the buffer + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); +} + +void drawString(int x, int y, char * string) +{ + OSScreenPutFontEx(0, x, y, string); + OSScreenPutFontEx(1, x, y, string); +} + +void fillScreen(char r,char g,char b,char a) +{ + uint32_t num = (r << 24) | (g << 16) | (b << 8) | a; + OSScreenClearBufferEx(0, num); + OSScreenClearBufferEx(1, num); +} + +//Rendering in +void drawPixel(int x, int y, char r, char g, char b, char a) +{ + uint32_t num = (r << 24) | (g << 16) | (b << 8) | a; + OSScreenPutPixelEx(0,x*2,y*2,num); + OSScreenPutPixelEx(1,x*2,y*2,num); + OSScreenPutPixelEx(0,x*2+1,y*2,num); + OSScreenPutPixelEx(1,x*2+1,y*2,num); + OSScreenPutPixelEx(0,x*2,y*2+1,num); + OSScreenPutPixelEx(1,x*2,y*2+1,num); + OSScreenPutPixelEx(0,x*2+1,y*2+1,num); + OSScreenPutPixelEx(1,x*2+1,y*2+1,num); + //Code to write to framebuffer directly. For some reason this is only writing to one of the framebuffers when calling flipBuffers. Should provide speedup but needs investigation. + /* + int buf0_size = OSScreenGetBufferSizeEx(0); + int height = 1024; + int width = 1280; + char *screen = (void *)screenBuffer; + uint32_t v=(x + y*width)*4; + screen[v]=r; + screen[v+1]=g; + screen[v+2]=b; + screen[v+3]=a; + + height = 480; + width = 896; + char *screen2 = (void *)screenBuffer + buf0_size; + v=(x + y*width)*4; + screen2[v]=r; + screen2[v+1]=g; + screen2[v+2]=b; + screen2[v+3]=a; + */ +} + +void drawLine(int x1, int y1, int x2, int y2, char r, char g, char b, char a) +{ + + int x, y; + if (x1 == x2){ + if (y1 < y2) for (y = y1; y <= y2; y++) drawPixel(x1, y, r, g, b, a); + else for (y = y2; y <= y1; y++) drawPixel(x1, y, r, g, b, a); + } + else { + if (x1 < x2) for (x = x1; x <= x2; x++) drawPixel(x, y1, r, g, b, a); + else for (x = x2; x <= x1; x++) drawPixel(x, y1, r, g, b, a); + } +} + +void drawRect(int x1, int y1, int x2, int y2, char r, char g, char b, char a) +{ + drawLine(x1, y1, x2, y1, r, g, b, a); + drawLine(x2, y1, x2, y2, r, g, b, a); + drawLine(x1, y2, x2, y2, r, g, b, a); + drawLine(x1, y1, x1, y2, r, g, b, a); +} + +void drawFillRect(int x1, int y1, int x2, int y2, char r, char g, char b, char a) +{ + int X1, X2, Y1, Y2, i, j; + + if (x1 < x2){ + X1 = x1; + X2 = x2; + } + else { + X1 = x2; + X2 = x1; + } + + if (y1 < y2){ + Y1 = y1; + Y2 = y2; + } + else { + Y1 = y2; + Y2 = y1; + } + for (i = X1; i <= X2; i++){ + for (j = Y1; j <= Y2; j++){ + drawPixel(i, j, r, g, b, a); + } + } +} + +void drawCircle(int xCen, int yCen, int radius, char r, char g, char b, char a) +{ + int x = 0; + int y = radius; + int p = (5 - radius * 4) / 4; + drawCircleCircum(xCen, yCen, x, y, r, g, b, a); + while (x < y){ + x++; + if (p < 0){ + p += 2 * x + 1; + } + else{ + y--; + p += 2 * (x - y) + 1; + } + drawCircleCircum(xCen, yCen, x, y, r, g, b, a); + } +} + +void drawFillCircle(int xCen, int yCen, int radius, char r, char g, char b, char a) +{ + drawCircle(xCen, yCen, radius, r, g, b, a); + int x, y; + for (y = -radius; y <= radius; y++){ + for (x = -radius; x <= radius; x++) + if (x*x + y*y <= radius*radius + radius * .8f) + drawPixel(xCen + x, yCen + y, r, g, b, a); + } +} + +void drawCircleCircum(int cx, int cy, int x, int y, char r, char g, char b, char a) +{ + + if (x == 0){ + drawPixel(cx, cy + y, r, g, b, a); + drawPixel(cx, cy - y, r, g, b, a); + drawPixel(cx + y, cy, r, g, b, a); + drawPixel(cx - y, cy, r, g, b, a); + } + if (x == y){ + drawPixel(cx + x, cy + y, r, g, b, a); + drawPixel(cx - x, cy + y, r, g, b, a); + drawPixel(cx + x, cy - y, r, g, b, a); + drawPixel(cx - x, cy - y, r, g, b, a); + } + if (x < y){ + drawPixel(cx + x, cy + y, r, g, b, a); + drawPixel(cx - x, cy + y, r, g, b, a); + drawPixel(cx + x, cy - y, r, g, b, a); + drawPixel(cx - x, cy - y, r, g, b, a); + drawPixel(cx + y, cy + x, r, g, b, a); + drawPixel(cx - y, cy + x, r, g, b, a); + drawPixel(cx + y, cy - x, r, g, b, a); + drawPixel(cx - y, cy - x, r, g, b, a); + } +} diff --git a/samples/pong/src/draw.h b/samples/pong/src/draw.h new file mode 100755 index 0000000..5f5a880 --- /dev/null +++ b/samples/pong/src/draw.h @@ -0,0 +1,19 @@ +#ifndef DRAW_H +#define DRAW_H +#include +#include + +void *screenBuffer; + +//Function declarations for my graphics library +void flipBuffers(); +void fillScreen(char r, char g, char b, char a); +void drawString(int x, int y, char * string); +void drawPixel(int x, int y, char r, char g, char b, char a); +void drawLine(int x1, int y1, int x2, int y2, char r, char g, char b, char a); +void drawRect(int x1, int y1, int x2, int y2, char r, char g, char b, char a); +void drawFillRect(int x1, int y1, int x2, int y2, char r, char g, char b, char a); +void drawCircle(int xCen, int yCen, int radius, char r, char g, char b, char a); +void drawFillCircle(int xCen, int yCen, int radius, char r, char g, char b, char a); +void drawCircleCircum(int cx, int cy, int x, int y, char r, char g, char b, char a); +#endif /* DRAW_H */ diff --git a/samples/pong/src/memory.c b/samples/pong/src/memory.c new file mode 100644 index 0000000..2d83baf --- /dev/null +++ b/samples/pong/src/memory.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include +#include +#include +#include +#include +#include "memory.h" + +#define MEMORY_ARENA_1 0 +#define MEMORY_ARENA_2 1 +#define MEMORY_ARENA_3 2 +#define MEMORY_ARENA_4 3 +#define MEMORY_ARENA_5 4 +#define MEMORY_ARENA_6 5 +#define MEMORY_ARENA_7 6 +#define MEMORY_ARENA_8 7 +#define MEMORY_ARENA_FG_BUCKET 8 + +static void *mem1_heap; +static void *bucket_heap; + +void memoryInitialize(void) +{ + void *mem1_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_1); + unsigned int mem1_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(mem1_heap_handle, 4); + void *mem1_memory = MEMAllocFromFrmHeapEx(mem1_heap_handle, mem1_allocatable_size, 4); + if(mem1_memory) + mem1_heap = MEMCreateExpHeapEx(mem1_memory, mem1_allocatable_size, 0); + + void *bucket_heap_handle = MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET); + unsigned int bucket_allocatable_size = MEMGetAllocatableSizeForFrmHeapEx(bucket_heap_handle, 4); + void *bucket_memory = MEMAllocFromFrmHeapEx(bucket_heap_handle, bucket_allocatable_size, 4); + if(bucket_memory) + bucket_heap = MEMCreateExpHeapEx(bucket_memory, bucket_allocatable_size, 0); +} + +void memoryRelease(void) +{ + MEMDestroyExpHeap(mem1_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_1), 3); + mem1_heap = NULL; + + MEMDestroyExpHeap(bucket_heap); + MEMFreeToFrmHeap(MEMGetBaseHeapHandle(MEMORY_ARENA_FG_BUCKET), 3); + bucket_heap = NULL; +} + +//!------------------------------------------------------------------------------------------- +//! some wrappers +//!------------------------------------------------------------------------------------------- +void * MEM2_alloc(unsigned int size, unsigned int align) +{ + return memalign(align, size); +} + +void MEM2_free(void *ptr) +{ + free(ptr); +} + +void * MEM1_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(mem1_heap, size, align); +} + +void MEM1_free(void *ptr) +{ + MEMFreeToExpHeap(mem1_heap, ptr); +} + +void * MEMBucket_alloc(unsigned int size, unsigned int align) +{ + if (align < 4) + align = 4; + return MEMAllocFromExpHeapEx(bucket_heap, size, align); +} + +void MEMBucket_free(void *ptr) +{ + MEMFreeToExpHeap(bucket_heap, ptr); +} diff --git a/samples/pong/src/memory.h b/samples/pong/src/memory.h new file mode 100644 index 0000000..59764d0 --- /dev/null +++ b/samples/pong/src/memory.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#ifndef __MEMORY_H_ +#define __MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void memoryInitialize(void); +void memoryRelease(void); + +void * MEM2_alloc(unsigned int size, unsigned int align); +void MEM2_free(void *ptr); + +void * MEM1_alloc(unsigned int size, unsigned int align); +void MEM1_free(void *ptr); + +void * MEMBucket_alloc(unsigned int size, unsigned int align); +void MEMBucket_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif // __MEMORY_H_ diff --git a/samples/pong/src/pong.c b/samples/pong/src/pong.c new file mode 100755 index 0000000..b3c58a7 --- /dev/null +++ b/samples/pong/src/pong.c @@ -0,0 +1,425 @@ +#include "pong.h" + +#include +#include + +//Sets a collsion box. +int collisionBox(int box1x, int box1y, int width1, int height1, int box2x, int box2y, int width2, int height2){ + int corner1x = box1x + width1; + int corner1y = box1y - height1; + int corner2x = box2x + width2; + int corner2y = box2y - height2; + + if (abs(box1x - corner2x)< 2 || abs(corner1x - box2x)< 2){ + if ((box1y >= corner2y && box1y <= box2y) || (corner1y >= corner2y && corner1y <= box2y))return 1; + + } + + if (abs(box1y - corner2y) < 2 || abs(corner1y - box2y) < 2){ + if ((box1x <= corner2x && box1x >= box2x) || (corner1x <= corner2x && corner1x >= box2x))return 2; + } + + + + return 0; +} + +//Updates player1 location +void p1Move(struct pongGlobals *myPongGlobals) { + + if ((myPongGlobals->button & VPAD_BUTTON_LEFT) && myPongGlobals->p1X > myPongGlobals->xMinBoundry) { + + //Trigger render flag + myPongGlobals->renderP1Flag = 1; + + //Update player location + myPongGlobals->p1X--; + + } + + if ((myPongGlobals->button & VPAD_BUTTON_RIGHT) && myPongGlobals->p1X+myPongGlobals->p1X_size < myPongGlobals->xMaxBoundry/4) { + + myPongGlobals->p1X++; + //Trigger render flag + myPongGlobals->renderP1Flag = 1; + } + + if ((myPongGlobals->button & VPAD_BUTTON_UP) && myPongGlobals->p1Y-myPongGlobals->p1Y_size > myPongGlobals->yMinBoundry) { + + //Trigger render flag + myPongGlobals->renderP1Flag = 1; + + //Update player location + myPongGlobals->p1Y--; + + } + if ((myPongGlobals->button & VPAD_BUTTON_DOWN) && myPongGlobals->p1Y < myPongGlobals->yMaxBoundry) { + + myPongGlobals->p1Y++; + //Trigger render flag + myPongGlobals->renderP1Flag = 1; + } + +}; + +//Updates player1 location +void p2Move(struct pongGlobals *myPongGlobals) { + + if ((myPongGlobals->button & VPAD_BUTTON_Y) && myPongGlobals->p2X > myPongGlobals->xMaxBoundry-myPongGlobals->xMaxBoundry/4) { + + //Trigger render flag + myPongGlobals->renderP2Flag = 1; + + //Update player location + myPongGlobals->p2X--; + + } + + if ((myPongGlobals->button & VPAD_BUTTON_A) && myPongGlobals->p2X+myPongGlobals->p2X_size < myPongGlobals->xMaxBoundry) { + + myPongGlobals->p2X++; + //Trigger render flag + myPongGlobals->renderP2Flag = 1; + } + + if ((myPongGlobals->button & VPAD_BUTTON_X) && myPongGlobals->p2Y-myPongGlobals->p2Y_size > myPongGlobals->yMinBoundry) { + + //Trigger render flag + myPongGlobals->renderP2Flag = 1; + + //Update player location + myPongGlobals->p2Y--; + + } + if ((myPongGlobals->button & VPAD_BUTTON_B) && myPongGlobals->p2Y < myPongGlobals->yMaxBoundry) { + + myPongGlobals->p2Y++; + //Trigger render flag + myPongGlobals->renderP2Flag = 1; + } + +}; + +//Physics for ball +void moveBall(struct pongGlobals *myPongGlobals) { + int jump = 1; + + //Don't move at all + if (myPongGlobals->flag)jump = 4; + + switch (myPongGlobals->direction) { + case 1: + myPongGlobals->ballX -= jump; //down left + myPongGlobals->ballY += jump; + break; + case 3: + myPongGlobals->ballX += jump; //down right + myPongGlobals->ballY += jump; + break; + case 2: + myPongGlobals->ballX += jump; //up right + myPongGlobals->ballY -= jump; + break; + case 0: + myPongGlobals->ballX -= jump; //up left + myPongGlobals->ballY -= jump; + break; + default: + break; + + } + + myPongGlobals->flag = 0; +}; + +//Checks for collsions +void checkCollision(struct pongGlobals *myPongGlobals) { + int old; + old = myPongGlobals->direction; + + if (myPongGlobals->ballY-myPongGlobals->ballY_size < myPongGlobals->yMinBoundry) { + myPongGlobals->direction ^= 1; + } + + /* + if (myPongGlobals->ballX < myPongGlobals->xMinBoundry) { + myPongGlobals->direction ^= 2; + } + + if (myPongGlobals->ballX > myPongGlobals->xMaxBoundry) { + myPongGlobals->direction ^= 2; + } + */ + + if (myPongGlobals->ballY > myPongGlobals->yMaxBoundry) { + myPongGlobals->direction ^= 1; + } + + //if (myPongGlobals->ballX < myPongGlobals->p1X+myPongGlobals->p1X_size+2) + { + //Check p1 collision + if (collisionBox(myPongGlobals->ballX, myPongGlobals->ballY, myPongGlobals->ballX_size, myPongGlobals->ballY_size, myPongGlobals->p1X, myPongGlobals->p1Y_old, myPongGlobals->p1X_size, myPongGlobals->p1Y_size) == 1) { + myPongGlobals->direction ^= 2; + } + else if (collisionBox(myPongGlobals->ballX, myPongGlobals->ballY, myPongGlobals->ballX_size, myPongGlobals->ballY_size, myPongGlobals->p1X, myPongGlobals->p1Y, myPongGlobals->p1X_size, myPongGlobals->p1Y_size) == 2) + { + myPongGlobals->direction ^= 1; + + } + } + //if (myPongGlobals->ballX+myPongGlobals->ballX_size > myPongGlobals->p2X-2) + { + //Check p2 collision + if (collisionBox(myPongGlobals->ballX, myPongGlobals->ballY, myPongGlobals->ballX_size, myPongGlobals->ballY_size, myPongGlobals->p2X, myPongGlobals->p2Y, myPongGlobals->p2X_size, myPongGlobals->p2Y_size) == 1) { + myPongGlobals->direction ^= 2; + } + else if (collisionBox(myPongGlobals->ballX, myPongGlobals->ballY, myPongGlobals->ballX_size, myPongGlobals->ballY_size, myPongGlobals->p2X, myPongGlobals->p2Y, myPongGlobals->p2X_size, myPongGlobals->p2Y_size) == 2) + { + myPongGlobals->direction ^= 1; + + } + } + if ((myPongGlobals->direction ^ old) != 0)myPongGlobals->flag = 1; + + if (myPongGlobals->ballX+myPongGlobals->ballX_size >= myPongGlobals->xMaxBoundry) + { + myPongGlobals->score1++; + checkWin(myPongGlobals); + } + + if (myPongGlobals->ballX <= myPongGlobals->xMinBoundry) + { + myPongGlobals->score2++; + checkWin(myPongGlobals); + } + +}; + +//Checks to see if we have meet the requirements for entering the win state +void checkWin(struct pongGlobals *myPongGlobals) { + if (myPongGlobals->score1 > myPongGlobals->scoreWin) { + myPongGlobals->score1 = 0; + myPongGlobals->renderWinFlag = 1; + myPongGlobals->winningPlayer = 1; + } + + if (myPongGlobals->score2 > myPongGlobals->scoreWin) { + myPongGlobals->score2 = 0; + myPongGlobals->renderWinFlag = 1; + myPongGlobals->winningPlayer = 2; + } + reset(myPongGlobals); + +}; + +//Render function for ball and updates player and balls new locations. +void renderBall(struct pongGlobals *myPongGlobals) { + drawFillRect(myPongGlobals->ballX_old, myPongGlobals->ballY_old - myPongGlobals->ballY_size, myPongGlobals->ballX_old + myPongGlobals->ballX_size, myPongGlobals->ballY_old, myPongGlobals->ballTrailColorR,myPongGlobals->ballTrailColorG,myPongGlobals->ballTrailColorB, 0); + drawFillRect(myPongGlobals->ballX, myPongGlobals->ballY - myPongGlobals->ballY_size, myPongGlobals->ballX + myPongGlobals->ballX_size, myPongGlobals->ballY, myPongGlobals->ballColorR, myPongGlobals->ballColorG, myPongGlobals->ballColorB, 0); +}; + +void render(struct pongGlobals *myPongGlobals) +{ + for (int ii = 0; ii < 2; ii++) + { + if (myPongGlobals->renderResetFlag) + { + renderReset(myPongGlobals); + } + if (myPongGlobals->renderScoreFlag) + { + renderScore(myPongGlobals); + } + + if (myPongGlobals->renderBallFlag) + { + renderBall(myPongGlobals); + } + + if (myPongGlobals->renderWinFlag) + { + renderWin(myPongGlobals); + } + + if (myPongGlobals->renderP1Flag) + { + renderP1(myPongGlobals); + } + + if (myPongGlobals->renderP2Flag) + { + renderP2(myPongGlobals); + } + flipBuffers(); + } + + resetRenderFlags(myPongGlobals); + + +} + +void resetRenderFlags(struct pongGlobals *myPongGlobals) +{ + myPongGlobals->renderResetFlag = 0; + myPongGlobals->renderBallFlag = 0; + myPongGlobals->renderWinFlag = 0; + myPongGlobals->renderP1Flag = 0; + myPongGlobals->renderP2Flag = 0; + myPongGlobals->renderScoreFlag=0; + +} + +void updatePosition(struct pongGlobals *myPongGlobals) +{ + myPongGlobals->p1X_old = myPongGlobals->p1X; + myPongGlobals->p1Y_old = myPongGlobals->p1Y; + myPongGlobals->p2X_old = myPongGlobals->p2X; + myPongGlobals->p2Y_old = myPongGlobals->p2Y; + myPongGlobals->ballX_old = myPongGlobals->ballX; + myPongGlobals->ballY_old = myPongGlobals->ballY; +} + +//Reset the game +void reset(struct pongGlobals *myPongGlobals) { + //Set global variables to default state + myPongGlobals->ballX = myPongGlobals->ballX_default; + myPongGlobals->ballY = myPongGlobals->ballY_default; + myPongGlobals->p1X = myPongGlobals->p1X_default; + myPongGlobals->p1Y = myPongGlobals->p1Y_default; + myPongGlobals->p1X_old = myPongGlobals->p1X; + myPongGlobals->p1Y_old = myPongGlobals->p1Y; + myPongGlobals->p2X = myPongGlobals->p2X_default; + myPongGlobals->p2Y = myPongGlobals->p2Y_default; + myPongGlobals->p2X_old = myPongGlobals->p2X; + myPongGlobals->p2Y_old = myPongGlobals->p2Y; + myPongGlobals->ballX_old = myPongGlobals->ballX; + myPongGlobals->ballY_old = myPongGlobals->ballY; + myPongGlobals->direction = (myPongGlobals->count & 3); + myPongGlobals->button = 0; + + //Set flag to render reset screen; + myPongGlobals->renderResetFlag = 1; + myPongGlobals->renderScoreFlag = 1; + +}; + +void renderScore(struct pongGlobals *myPongGlobals) +{ + char output1[255]; + __os_snprintf(output1, 255, "%d", myPongGlobals->score1); + drawString(myPongGlobals->score1X, myPongGlobals->score1Y, output1); + char output2[255]; + __os_snprintf(output2, 255, "%d", myPongGlobals->score2); + drawString(myPongGlobals->score2X, myPongGlobals->score2Y, output2); + +} + +void renderReset(struct pongGlobals *myPongGlobals) +{ + fillScreen(myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB,0); + renderInitialPlayers(myPongGlobals); +} + +//Sleeping function to kill time. Should probably update this to use tick. +void wait(int t) { + int i = 0; + int j = 0; + int z = 0; + + for (i = 0; i < t; i++) { + for (j = 0; j < t; j++) { + z = i / 33; + } + } + +}; + + +//Draws the win screen. +void renderWin(struct pongGlobals *myPongGlobals) { + if (myPongGlobals->winningPlayer == 1) { + char p1win[255]; + __os_snprintf(p1win, 255, "Player 1 Wins!"); + drawString(myPongGlobals->winX, myPongGlobals->winY, p1win); + } + if (myPongGlobals->winningPlayer == 2) { + char p2win[255]; + __os_snprintf(p2win, 255, "Player 2 Wins!"); + drawString(myPongGlobals->winX, myPongGlobals->winY, p2win); + } +}; + +//Draws the inital player paddles and ball. +void renderInitialPlayers(struct pongGlobals *myPongGlobals) { + drawFillRect(myPongGlobals->p1X_old, myPongGlobals->p1Y_old - myPongGlobals->p1Y_size, myPongGlobals->p1X_old + myPongGlobals->p1X_size, myPongGlobals->p1Y_old, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + + drawFillRect(myPongGlobals->p2X_old, myPongGlobals->p2Y_old - myPongGlobals->p2Y_size, myPongGlobals->p2X_old + myPongGlobals->p2X_size, myPongGlobals->p2Y_old, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + drawFillRect(myPongGlobals->ballX_old, myPongGlobals->ballY_old - myPongGlobals->ballY_size, myPongGlobals->ballX_old + myPongGlobals->ballX_size, myPongGlobals->ballY_old, myPongGlobals->ballColorR, myPongGlobals->ballColorG, myPongGlobals->ballColorB, 0); + + char credits[255]; + __os_snprintf(credits, 255, "Pong by Relys!"); + drawString(myPongGlobals->winX, myPongGlobals->winY+1, credits); +}; + +//Draws player1's paddle +void renderP1(struct pongGlobals *myPongGlobals) { + //move up + if (myPongGlobals->p1Y_old>myPongGlobals->p1Y) + { + drawLine(myPongGlobals->p1X_old, myPongGlobals->p1Y_old, myPongGlobals->p1X_old + myPongGlobals->p1X_size, myPongGlobals->p1Y_old, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + + drawLine(myPongGlobals->p1X, myPongGlobals->p1Y - myPongGlobals->p1Y_size, myPongGlobals->p1X + myPongGlobals->p1X_size, myPongGlobals->p1Y - myPongGlobals->p1Y_size, myPongGlobals->paddleColorR,myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + } + //Move down + if(myPongGlobals->p1Y_oldp1Y) + { + drawLine(myPongGlobals->p1X, myPongGlobals->p1Y, myPongGlobals->p1X + myPongGlobals->p1X_size, myPongGlobals->p1Y, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + drawLine(myPongGlobals->p1X_old, myPongGlobals->p1Y_old - myPongGlobals->p1Y_size, myPongGlobals->p1X_old + myPongGlobals->p1X_size, myPongGlobals->p1Y_old - myPongGlobals->p1Y_size, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + } + + //Move right + if(myPongGlobals->p1X_oldp1X) + { + drawLine(myPongGlobals->p1X_old, myPongGlobals->p1Y_old-myPongGlobals->p1Y_size, myPongGlobals->p1X_old , myPongGlobals->p1Y_old, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + drawLine(myPongGlobals->p1X+myPongGlobals->p1X_size, myPongGlobals->p1Y-myPongGlobals->p1Y_size, myPongGlobals->p1X+myPongGlobals->p1X_size, myPongGlobals->p1Y, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + } + + //Move left + if(myPongGlobals->p1X_old>myPongGlobals->p1X) + { + drawLine(myPongGlobals->p1X, myPongGlobals->p1Y-myPongGlobals->p1Y_size, myPongGlobals->p1X , myPongGlobals->p1Y, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + drawLine(myPongGlobals->p1X_old+myPongGlobals->p1X_size, myPongGlobals->p1Y_old-myPongGlobals->p1Y_size, myPongGlobals->p1X_old+myPongGlobals->p1X_size, myPongGlobals->p1Y_old, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + } +} + +//Draws player2's paddle +void renderP2(struct pongGlobals *myPongGlobals) { + //move up + if (myPongGlobals->p2Y_old>myPongGlobals->p2Y) + { + drawLine(myPongGlobals->p2X_old, myPongGlobals->p2Y_old, myPongGlobals->p2X_old + myPongGlobals->p2X_size, myPongGlobals->p2Y_old, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + + drawLine(myPongGlobals->p2X, myPongGlobals->p2Y - myPongGlobals->p2Y_size, myPongGlobals->p2X + myPongGlobals->p2X_size, myPongGlobals->p2Y - myPongGlobals->p2Y_size, myPongGlobals->paddleColorR,myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + } + //Move down + if(myPongGlobals->p2Y_oldp2Y) + { + drawLine(myPongGlobals->p2X, myPongGlobals->p2Y, myPongGlobals->p2X + myPongGlobals->p2X_size, myPongGlobals->p2Y, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + drawLine(myPongGlobals->p2X_old, myPongGlobals->p2Y_old - myPongGlobals->p2Y_size, myPongGlobals->p2X_old + myPongGlobals->p2X_size, myPongGlobals->p2Y_old - myPongGlobals->p2Y_size, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + } + + //Move right + if(myPongGlobals->p2X_oldp2X) + { + drawLine(myPongGlobals->p2X_old, myPongGlobals->p2Y_old-myPongGlobals->p2Y_size, myPongGlobals->p2X_old , myPongGlobals->p2Y_old, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + drawLine(myPongGlobals->p2X+myPongGlobals->p2X_size, myPongGlobals->p2Y-myPongGlobals->p2Y_size, myPongGlobals->p2X+myPongGlobals->p2X_size, myPongGlobals->p2Y, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + } + + //Move left + if(myPongGlobals->p2X_old>myPongGlobals->p2X) + { + drawLine(myPongGlobals->p2X, myPongGlobals->p2Y-myPongGlobals->p2Y_size, myPongGlobals->p2X , myPongGlobals->p2Y, myPongGlobals->paddleColorR, myPongGlobals->paddleColorG, myPongGlobals->paddleColorB, 0); + drawLine(myPongGlobals->p2X_old+myPongGlobals->p2X_size, myPongGlobals->p2Y_old-myPongGlobals->p2Y_size, myPongGlobals->p2X_old+myPongGlobals->p2X_size, myPongGlobals->p2Y_old, myPongGlobals->backgroundColorR, myPongGlobals->backgroundColorG, myPongGlobals->backgroundColorB, 0); + } + +} diff --git a/samples/pong/src/pong.h b/samples/pong/src/pong.h new file mode 100755 index 0000000..4d0138d --- /dev/null +++ b/samples/pong/src/pong.h @@ -0,0 +1,109 @@ +#ifndef PONG_H +#define PONG_H +#include +#include +//Using modified version of draw to render at twice the scale to improve framerate +#include "draw.h" +//Struct for global variables for pong +struct pongGlobals{ + //Flag for restarting the entire game. + int restart; + + //Gameplay boundry + int xMinBoundry; + int xMaxBoundry; + int yMinBoundry; + int yMaxBoundry; + int scale; + int score1X; + int score2X; + int score1Y; + int score2Y; + int winX; + int winY; + + //Globals for ball location and movement dx/dy + int ballX; + int ballX_old; + int ballY; + int ballY_old; + int ballX_size; + int ballY_size; + + //Globals for player1 location and movement dx/dy + int p1X; + int p1X_old; + int p1Y; + int p1Y_old; + int p1X_size; + int p1Y_size; + + //Globals for player2 location and movement dx/dy + int p2X; + int p2X_old; + int p2Y; + int p2Y_old; + int p2X_size; + int p2Y_size; + + int p1X_default; + int p2X_default; + int ballX_default; + int p1Y_default; + int p2Y_default; + int ballY_default; + + //Game engine globals + int direction; + uint32_t button; + int paddleColorR; + int paddleColorG; + int paddleColorB; + int ballColorR; + int ballColorG; + int ballColorB; + int ballTrailColorR; + int ballTrailColorG; + int ballTrailColorB; + int backgroundColorR; + int backgroundColorG; + int backgroundColorB; + int count; + + int score1; + int score2; + int scoreWin; + + int flag; + + int winningPlayer; + + int renderP1Flag; + int renderP2Flag; + + int renderResetFlag; + int renderBallFlag; + int renderWinFlag; + int renderScoreFlag; +}; + +//Function declarations for pong functions. +void renderP2(struct pongGlobals *myPongGlobals); +void renderP1(struct pongGlobals *myPongGlobals); +void renderInitialPlayers(struct pongGlobals *myPongGlobals); +void renderWin(struct pongGlobals *myPongGlobals); +void wait(int t); +void renderReset(struct pongGlobals *myPongGlobals); +void renderScore(struct pongGlobals *myPongGlobals); +void reset(struct pongGlobals *myPongGlobals); +void updatePosition(struct pongGlobals *myPongGlobals); +void resetRenderFlags(struct pongGlobals *myPongGlobals); +void render(struct pongGlobals *myPongGlobals); +void renderBall(struct pongGlobals *myPongGlobals); +void checkWin(struct pongGlobals *myPongGlobals); +void checkCollision(struct pongGlobals *myPongGlobals); +void moveBall(struct pongGlobals *myPongGlobals); +void p2Move(struct pongGlobals *myPongGlobals); +void p1Move(struct pongGlobals *myPongGlobals); +int collisionBox(int box1x, int box1y, int width1, int height1, int box2x, int box2y, int width2, int height2); +#endif /* PONG_H */ diff --git a/samples/pong/src/program.c b/samples/pong/src/program.c new file mode 100755 index 0000000..884f1d6 --- /dev/null +++ b/samples/pong/src/program.c @@ -0,0 +1,184 @@ +#include "program.h" + +#include +#include +#include +#include +#include +#include +#include +#include "memory.h" + +char log_buf[0x400]; + +int main(int argc, char **argv) +{ + memoryInitialize(); + OSReport("Memory initialized\n"); + + /****************************> Globals <****************************/ + struct pongGlobals myPongGlobals; + //Flag for restarting the entire game. + myPongGlobals.restart = 1; + //scale of game + myPongGlobals.scale=1; + //Default locations for paddles and ball location and movement dx/dy + myPongGlobals.p1X_default=40*myPongGlobals.scale; + myPongGlobals.p2X_default=340*myPongGlobals.scale; + myPongGlobals.ballX_default=200*myPongGlobals.scale; + myPongGlobals.p1Y_default=150*myPongGlobals.scale; + myPongGlobals.p2Y_default=150*myPongGlobals.scale; + myPongGlobals.ballY_default=120*myPongGlobals.scale; + //Sizes of objects + myPongGlobals.p1X_size=20*myPongGlobals.scale; + myPongGlobals.p1Y_size=60*myPongGlobals.scale; + myPongGlobals.ballX_size=8*myPongGlobals.scale; + myPongGlobals.ballY_size=8*myPongGlobals.scale; + myPongGlobals.p2X_size=20*myPongGlobals.scale; + myPongGlobals.p2Y_size=60*myPongGlobals.scale; + //Boundry of play area (screen) + myPongGlobals.xMinBoundry=0*myPongGlobals.scale; + myPongGlobals.xMaxBoundry=400*myPongGlobals.scale; + myPongGlobals.yMinBoundry=0*myPongGlobals.scale; + myPongGlobals.yMaxBoundry=240*myPongGlobals.scale; + + myPongGlobals.winX=11*2*myPongGlobals.scale; + myPongGlobals.winY=5*2*myPongGlobals.scale; + myPongGlobals.score1X=13*2*myPongGlobals.scale; + myPongGlobals.score2X=15*2*myPongGlobals.scale; + myPongGlobals.score1Y=0*myPongGlobals.scale; + myPongGlobals.score2Y=0*myPongGlobals.scale; + //Game engine globals + myPongGlobals.direction = 1; + myPongGlobals.button = 0; + myPongGlobals.paddleColorR=0xFF; + myPongGlobals.paddleColorG=0x00; + myPongGlobals.paddleColorB=0x00; + myPongGlobals.ballColorR=0x00; + myPongGlobals.ballColorG=0xFF; + myPongGlobals.ballColorB=0x00; + myPongGlobals.ballTrailColorR=0x00; + myPongGlobals.ballTrailColorG=0x00; + myPongGlobals.ballTrailColorB=0xFF; + myPongGlobals.backgroundColorR=0x00; + myPongGlobals.backgroundColorG=0x00; + myPongGlobals.backgroundColorB=0x00; + myPongGlobals.count = 0; + //Keep track of score + myPongGlobals.score1 = 0; + myPongGlobals.score2 = 0; + myPongGlobals.scoreWin = 9; + //Game engine globals + myPongGlobals.direction = 1; + myPongGlobals.button = 0; + myPongGlobals.paddleColorR=0xFF; + myPongGlobals.paddleColorG=0x00; + myPongGlobals.paddleColorB=0x00; + myPongGlobals.ballColorR=0x00; + myPongGlobals.ballColorG=0xFF; + myPongGlobals.ballColorB=0x00; + myPongGlobals.ballTrailColorR=0x00; + myPongGlobals.ballTrailColorG=0x00; + myPongGlobals.ballTrailColorB=0xFF; + myPongGlobals.backgroundColorR=0x00; + myPongGlobals.backgroundColorG=0x00; + myPongGlobals.backgroundColorB=0x00; + myPongGlobals.count = 0; + //Keep track of score + myPongGlobals.score1 = 0; + myPongGlobals.scoreWin = 9; + //Used for collision + myPongGlobals.flag = 0; + + //Flag to determine if p1 should be rendered along with p1's movement direction + myPongGlobals.renderP1Flag = 0; + //Flags for render states + myPongGlobals.renderResetFlag = 0; + myPongGlobals.renderBallFlag = 0; + myPongGlobals.renderWinFlag = 0; + myPongGlobals.renderScoreFlag = 0; + OSReport("Globals initialized\n"); + + //Call the Screen initilzation function. + OSScreenInit(); + OSReport("Screen initted\n"); + //Grab the buffer size for each screen (TV and gamepad) + int buf0_size = OSScreenGetBufferSizeEx(0); + int buf1_size = OSScreenGetBufferSizeEx(1); + __os_snprintf(log_buf, 0x400, "Screen sizes %x, %x\n", buf0_size, buf1_size); + OSReport(log_buf); + + //Set the buffer area. + screenBuffer = MEM1_alloc(buf0_size + buf1_size, 0x40); + __os_snprintf(log_buf, 0x400, "Allocated screen buffers at %x\n", screenBuffer); + OSReport(log_buf); + + OSScreenSetBufferEx(0, screenBuffer); + OSScreenSetBufferEx(1, (screenBuffer + buf0_size)); + OSReport("Set screen buffers\n"); + + OSScreenEnableEx(0, 1); + OSScreenEnableEx(1, 1); + + //Clear both framebuffers. + for (int ii = 0; ii < 2; ii++) + { + fillScreen(0,0,0,0); + flipBuffers(); + } + OSReport("Screen initialized\n"); + + /****************************> VPAD Loop <****************************/ + int error; + VPADStatus vpad_data; + while (1) + { + VPADRead(0, &vpad_data, 1, &error); + //Get the status of the gamepad + myPongGlobals.button = vpad_data.hold; + //If the game has been restarted, reset the game (we do this one time in the beginning to set everything up) + if (myPongGlobals.restart == 1) + { + OSReport("Game reset\n"); + reset(&myPongGlobals); + myPongGlobals.restart = 0; + } + //Set old positions. + updatePosition(&myPongGlobals); + + //Update location of player1 and 2 paddles + p1Move(&myPongGlobals); + p2Move(&myPongGlobals); + + //Update location of the ball + moveBall(&myPongGlobals); + //Check if their are any collisions between the ball and the paddles. + checkCollision(&myPongGlobals); + //Render the scene + myPongGlobals.renderBallFlag = 1; + render(&myPongGlobals); + + //Increment the counter (used for physicals calcuations) + myPongGlobals.count+=1; + + //To exit the game + if (myPongGlobals.button & VPAD_BUTTON_HOME) + { + break; + } + } + //WARNING: DO NOT CHANGE THIS. YOU MUST CLEAR THE FRAMEBUFFERS AND IMMEDIATELY CALL EXIT FROM THIS FUNCTION. RETURNING TO LOADER CAUSES FREEZE. + for(int ii = 0; ii < 2; ii++) + { + fillScreen(0,0,0,0); + flipBuffers(); + } + + //TODO: This doesn't work? + OSReport("Exiting to menu\n"); + memoryRelease(); + SYSLaunchMenu(); + exit(0); + + return 0; +} diff --git a/samples/pong/src/program.h b/samples/pong/src/program.h new file mode 100755 index 0000000..e2cf2fa --- /dev/null +++ b/samples/pong/src/program.h @@ -0,0 +1,11 @@ +#ifndef PROGRAM_H +#define PROGRAM_H + +//Using modified version of draw to render at twice the scale to improve framerate +#include "draw.h" + +#include "pong.h" + +void _entryPoint(); + +#endif /* PROGRAM_H */