Main file:
Code: Select all
//this is needed by KOS
#define _arch_dreamcast
#include <kos.h>
#include <stdlib.h>
#include <cmath>
#include "DCTile.h"
//screen dimensions
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Create instance of class player
Player dude;
//how much an object gets pulled down per frame
float Gravity = 0.38;
//array holding map data (0 or 1 for now)
int map[20][15];
//Create 3 bullets that may be shot
Bullet bullet[3];
#include "gun.cpp"
#include "quad.cpp"
#include "vmu.cpp"
int main() {
srand(time(NULL));
vid_set_mode(DM_640x480, PM_RGB565);
pvr_init_defaults();
cont_btn_callback(0, CONT_START | CONT_A | CONT_B | CONT_X | CONT_Y, (void (*)(unsigned char, long unsigned int))arch_exit);
//Init player
dude.m_x = (3*32);
dude.m_y = (10*32);
dude.m_dir = 1;
//clear map array
for(int x=0; x<=19; x++)
{
for(int y=0; y<=14; y++)
{
map[x][y] = 0;
}
}
//put some solids into the map array
for(int x=0; x<=19; x++)
{
map[x][0] = 1;
map[x][1] = 1;
map[x][12] = 1;
map[x][13] = 1;
map[x][14] = 1;
}
//add some more solids yo
map[0][9] = 1;
map[0][10] = 1;
map[0][11] = 1;
map[12][6] = 1;
map[13][6] = 1;
map[14][6] = 1;
map[15][6] = 1;
map[16][6] = 1;
/*map[5][6] = 1;
map[6][6] = 1;
map[7][6] = 1;
map[8][6] = 1;*/
map[16][6] = 1;
map[17][11] = 1;
map[18][11] = 1;
for(int y=0; y<15; y++)
{
map[19][y] = 1;
}
//take out some tiles yo
map[8][12] = 0;
map[9][12] = 0;
map[10][12] = 0;
map[11][12] = 0;
map[12][12] = 0;
SetVMU();
while(1) {
//move dude in persective of velocities
MoveHorizontal(dude.m_xvel,dude.m_x,dude.m_y,0,32,0,64);
if(MoveVertical(dude.m_yvel,dude.m_x,dude.m_y,0,32,0,64) == 1)
{ dude.m_jump = false; }
//simulate gravity (probably should be in jump function later)
dude.m_yvel = (dude.m_yvel + Gravity);
//simulate friction
if(dude.m_xvel < 0) { dude.m_xvel = (dude.m_xvel + Gravity); }
if(dude.m_xvel > 0) { dude.m_xvel = (dude.m_xvel - Gravity); }
//sorry, can't jump while falling :D
if(dude.m_yvel > 1) { dude.m_jump = true; }
DrawFrame();
GetInput();
Friction();
}
return 0;
}
void DrawFrame() {
pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY); // Non-transparent graphics
pvr_list_finish();
pvr_list_begin(PVR_LIST_TR_POLY); // Transparent graphics
DrawMap();
DrawPlayer();
UpdateBullets();
pvr_list_finish();
pvr_scene_finish();
}
void DrawMap() {
//draw the map
for(int x=0; x<=19; x++)
{
for(int y=0; y<=14; y++)
{
if(map[x][y] == 1)
{
//Draw dark box for tile
draw_tr_quad(x*32 + 16, y*32, 1, 32, 32, 1, 256-1, 256-255, 256-1);
//Draw lighter outline
draw_tr_quad((x*32)+1 + 16, (y*32)+1, 2, 30, 30, 1, 256-1, 256-180, 256-1);
}
}
}
}
void GetInput() {
cont_cond_t cond;
cont_get_cond(maple_addr(0,0),&cond);
if(!(cond.buttons & CONT_A)){
//if we are not currently jumping, and A wasn't held
if((dude.m_jump == false) && (dude.m_letgo == true)) {
//set some vars
dude.m_letgo = false;
dude.m_jump = true;
//at this point, we could put in an if statement to see if dude
//is moving fast enough to jump higer.. but not right now.
dude.m_jumptimer = 8;
//make dude bounce into action
dude.m_yvel = -4.5;
}
}
else {
//if dude isn't going up or down, reset letgo to true
if(abs((int)dude.m_yvel) < 1) dude.m_letgo = true;
//reset the jumptimer to 0
dude.m_jumptimer = 0;
}
//if we are currently jumping
if((dude.m_jump == true) && (dude.m_jumptimer > 0)) {
//adjust velocity for life
dude.m_yvel = dude.m_yvel - 1;
//decrease the jump timer
dude.m_jumptimer--;
}
if(!(cond.buttons & CONT_DPAD_LEFT)) {
dude.m_xvel = (dude.m_xvel - 1);
dude.m_dir = 0;
}
if(cond.joyx < 40){
dude.m_xvel = (dude.m_xvel - 1);
dude.m_dir = 0;
}
if(!(cond.buttons & CONT_DPAD_RIGHT)) {
dude.m_xvel = (dude.m_xvel + 1);
dude.m_dir = 1;
}
if(cond.joyx > 215){
dude.m_xvel = (dude.m_xvel + 1);
dude.m_dir = 1;
}
if(cond.rtrig > 100) {
if(dude.m_canshoot == true) {
Shoot((int)dude.m_x, (int)dude.m_y, dude.m_dir);
dude.m_canshoot = false;
}
}
if(cond.rtrig < 100)
dude.m_canshoot = true;
if(cond.ltrig > 100) dude.LevelUp();
if(!(cond.buttons & CONT_Y))
vid_screen_shot("/pc/screenshot.ppm");
}
void Friction() {
//keep dude from going left or right to fast
if(abs((int)dude.m_xvel) > 3) {
//if velocity less then 0
if(dude.m_xvel < 0) {
dude.m_xvel = (-3);
}
else {
dude.m_xvel = (3);
}
}
/*
//keep dude from going up or down to fast
if(abs((int)dude.m_yvel) > 6){
//if velocity less then 0
if(dude.m_yvel < 0) {
dude.m_yvel = (-6);
}
}
*/
}
void DrawPlayer() {
draw_tr_quad((int)dude.m_x + 16, (int)dude.m_y + 16, 1, 32, 64, 1, 256-1, 256-140, 256-255);
draw_tr_quad((int)dude.m_x+1 + 16, (int)dude.m_y+1 + 16, 2, 30, 62, 1, 256-1, 256-1, 256-255);
}
int MoveHorizontal(float& p_xvel, float& p_x, float& p_y, int p_left, int p_right, int p_top, int p_bottom)
{
for(int i=1; i<=abs( (int)p_xvel ); i++ )
{
//temporarily define the object's bounderies
int BoundLeft = ((int)p_x + p_left);
int BoundRight = ((int)p_x + p_right-1);
int BoundTop = ((int)p_y + p_top);
int BoundBottom = ((int)p_y + p_bottom-1);
//set temp Move = true? vars to false
bool MoveLeft = false;
bool MoveRight = false;
//loop from boundtop to boundbottom (replace loop with mar's idea!)
for(int Point=BoundTop; Point<=BoundBottom; Point++)
{
//if object going left
if(p_xvel < 0)
{
//if object's left bound minus 1 is in a solid tile
if(map[ (BoundLeft-1)/32 ][ (Point)/32 ] == 1)
{
//set the object's xvel to 0 and return with -1
p_xvel = 0;
return -1;
}
else
{
//set the MoveLeft var to true
MoveLeft = true;
}
}
//if object going right
if(p_xvel > 0)
{
//if object's right bound plus 1 is in a solid tile
if(map[ (BoundRight+1)/32 ][ (Point)/32 ] == 1)
{
//set the object's xvel to 0 and return with 1
p_xvel = 0;
return 1;
}
else
{
//set the MoveRight var to true
MoveRight = true;
}
}
}
//if the Move vars are now true, adjust the x values
if(MoveLeft == true) { p_x = p_x - 1; }
if(MoveRight == true) { p_x = p_x + 1; }
//if the object has gone out of array bounds, push it back on
if(p_x < 0) { p_x = 0; p_xvel = 0; }
if(p_x > 640) { p_x = 640; p_xvel = 0; } //replace 20*32 with map height var/function
}
//if no solids were hit at all, return 0
return 0;
}
//MoveVertical() - moves thing based on velocity
//returns -1 if top boundry hits a solid
// 1 if bottom boundry hits a solid
// 0 if no collision detected in move
int MoveVertical(float& p_yvel, float& p_x, float& p_y, int p_left, int p_right, int p_top, int p_bottom)
{
for(int i=1; i<=abs( (int)p_yvel ); i++ )
{
//temporarily define the object's bounderies
int BoundLeft = ((int)p_x + p_left);
int BoundRight = ((int)p_x + p_right-1);
int BoundTop = ((int)p_y + p_top);
int BoundBottom = ((int)p_y + p_bottom-1);
//set temp Move = true? vars to false
bool MoveUp = false;
bool MoveDown = false;
//loop from boundleft to boundright (replace loop with mar's idea!)
for(int Point=BoundLeft; Point<=BoundRight; Point++)
{
//if object going up
if(p_yvel < 0)
{
//if object's top bound minus 1 is in a solid tile
if(map[ (Point)/32 ][ (BoundTop-1)/32 ] == 1)
{
//set the object's yvel to 0 and return with -1
p_yvel = 0;
return -1;
}
else
{
//set the MoveUp var to true
MoveUp = true;
}
}
//if object going down
if(p_yvel > 0)
{
//if object's bottom bound plus 1 is in a solid tile
if(map[ (Point)/32 ][ (BoundBottom+1)/32 ] == 1)
{
//set the object's yvel to 0 and return with 1
p_yvel = 0;
return 1;
}
else
{
//set the MoveDown var to true
MoveDown = true;
}
}
}
//if the Move vars are now true, adjust the y values
if(MoveUp == true) { p_y = p_y - 1; }
if(MoveDown == true) { p_y = p_y + 1; }
//if the object has gone out of array bounds, push it back on
if(p_y < 0) { p_y = 0; p_yvel = 0; }
if(p_y > 15*32) { p_y = 15*32; p_yvel = 0; } //replace 15*32 with map height var/function
}
//if no solids were hit at all, return 0
return 0;
}
Code: Select all
// Function Prototypes
void DrawFrame();
void Friction();
void DrawMap();
void DrawPlayer();
void GetInput();
int MoveHorizontal(float& p_xvel, float& p_x, float& p_y, int p_left, int p_right, int p_top, int p_bottom);
int MoveVertical(float& p_yvel, float& p_x, float& p_y, int p_left, int p_right, int p_top, int p_bottom);
void Shoot(int x, int y, bool dir);
void UpdateBullets();
void draw_tr_quad(int x, int y, int z, int w, int h, int a, int r, int g, int b);
void SetVMU();
// Classes
class Player {
public:
//general movement
float m_x, m_y;
float m_xvel, m_yvel;
//jumping
bool m_jump;
bool m_letgo; //keeps track if the user is holding down space
bool m_canshoot; //keeps track if the user can shoot
bool m_dir;
float m_jumptimer;
//stats
int level, exp;
int attack, defense, hp;
int avgbattle_time, avgbattle_hits;
//constructor
Player() {
m_x = 0;
m_y = 0;
m_xvel = 0;
m_yvel = 0;
m_jump = false;
m_letgo = true;
m_jumptimer = 0;
m_canshoot = true;
level = 0;
exp = 0;
attack = 5;
defense = 5;
hp = 10;
avgbattle_time = 0;
avgbattle_hits = 0;
}
void CheckLevelUp() {
if(exp >= 100+(25*level)) LevelUp();
}
void LevelUp() {
unsigned short int hp_base = 0, attack_base = 0, defense_base = 0, hp_bonus = 0, attack_bonus = 0, defense_bonus = 0;
//base stat increases
hp_base += rand()%2 + 1;
attack_base += rand()%2 + 1;
defense_base += rand()%2 + 1;
printf("Hp base: %d\nAttack base: %d\nDefense base: %d\n", hp_base, attack_base, defense_base);
//bonus stat increases
if(avgbattle_hits == 0) hp_bonus += 3;
if(avgbattle_hits > 0 && avgbattle_hits < 3) hp_bonus += 2;
if(avgbattle_hits > 2 && avgbattle_hits < 5) hp_bonus++;
if(avgbattle_time > 0 && avgbattle_time < 601) attack_bonus += 3;
if(avgbattle_time > 600 && avgbattle_time < 1561) attack_bonus += 2;
if(avgbattle_time > 1560 && avgbattle_time < 2101) attack_bonus++;
defense_bonus = rand()%hp_bonus + 1;
printf("Hp bonus: %d\nAttack bonus: %d\nDefense bonus: %d\n", hp_bonus, attack_bonus, defense_bonus);
level++;
exp = 0;
}
};
class Bullet {
public:
int x;
int y;
bool active;
int direction;
};
Code: Select all
void SetVMU() {
static const char vmu[] = {
".....++.+++++++...+++++.+.++++..++++++++++++++++"
"++.++.+.++.+++.++++++++.+.+.+.++.+.+++++++++++++"
"++.++++.+.+.++.++++..++.+.+++.+++++++..++.+..+++"
"++.++.+.+...++.+++.++.+.+.+.++..++.+.++.+..++.++"
"++.++.+.+.++++.+++.++.+.+.+.++++.+.+.++.+.+++.++"
"++.++.+.++..+++...+..++.+.+.+...++.++..++.+++.++"
"++++++++++++++++++++++++++++++++++++++++++++++++"
"..++++++...+++++++++++++++++++++.+++++...+++++++"
".+.++++.+++++++.+.++.+.+.+.+.+.+.+++.+.+++++++++"
"..+++++.+..+.+...+..+..+..+...+...++++...+++++++"
".+..+.+.++.++.+.+++.+..+..+..+++.+.+.+++.+++++++"
"..++.+++...+.++.++++.++.++.+.+++..++.+...+++++++"
"+++.+++++++.++++++++++++++++++++++++++++++++++++"
"++++++........++.+++.+++++++++++++++++++++++++++"
"++++++++.++.++++.++.+..++++.+++++.+.+.+++.++++++"
"++++++++.++...++.++.....+.+..+.++++..+.+.+.+++++"
"++++++.+.++++.++.++.++.+.+..+.+.+.+.++.+.+.+++++"
"+++++++..++...++...+...+.+..+.+.+.+.++.++..+++++"
"++++++++++++++++++++++++++++++++++++++++.+.+++++"
"++++++++++++++++++++++.+.++..++++++++++++.++++++"
"++++++....+++...++++.+..+.+.++++++.++++.++.+++++"
"+++++++.+.+++..++++.+...+++.+.+...+.+.+.+.++++++"
"+++++++.++.+.+....+....+.+.....++....+...+++++++"
"+++++++.++.+.++..+..++.++.+.+.+++.++.+..+.++++++"
"+++++++.+++.++....++.....++.+.++++..+...++.+++++"
"++++++++++++++++.+++++++++++++++++++++++++++++++"
"++++++++++++++++.+++++++++++++++++++++++++++++++"
"....+++..++...++++++++......+++..+++++++++++++++"
"+.+.++.++..++.+++.++.+.++.+.+.+.++.++..+.+.+.+.+"
"+.+......+.++....+..+.......++......+.+.+...+.+."
"+.+.+..+++.++.+..+..+.++..+.+.+.++.++.+.+..++.+."
"+.+.+.+..++...+.+..+.+....++..+.++.....+.+.++.+."};
vmu_set_icon(vmu);
uint8 logo_bits[48*32/8]; // Setting VMU dimensions (48x32)
int x, y;
for (y=0; y<32; y++) {
for (x=0; x<48/8; x++) {
logo_bits[y*48/8 + x] = vmu[(31-y)*48/8 + ((48/8 - 1) - x)];
}
}
}
Code: Select all
void Shoot(int x, int y, bool dir) {
for(int i=0; i<3; i++) {
if(bullet[i].active == false) {
bullet[i].active = true;
bullet[i].x = x;
bullet[i].y = y + 20;
bullet[i].direction = dir;
break;
}
}
}
void UpdateBullets() {
for(int a=0; a<3; a++) {
if(bullet[a].active) {
if(bullet[a].direction == 0) bullet[a].x -= 14; // Left
if(bullet[a].direction == 1) bullet[a].x += 14; // Right
draw_tr_quad(bullet[a].x, bullet[a].y - 16, 5, 4, 4, 1, 256-255, 256-1, 256-1);
if(bullet[a].x < 0 || bullet[a].x > 640 || bullet[a].y < 0 || bullet[a].y > 480) {
bullet[a].active = false;
}
else{
for(int Point = bullet[a].y; Point < bullet[a].y+4; Point++){
if(map[ (bullet[a].x)/32 ][ (Point)/32 ] == 1) {
map[ (bullet[a].x)/32 ][ (Point)/32 ] = 0;
bullet[a].active = false;
}
}
}
}
}
}
GAH! I forgot the main part that you need to see. The untextured quad drawing function with the PVR:
quad.cpp
Code: Select all
void draw_tr_quad(int x, int y, int z, int w, int h, int a, int r, int g, int b) {
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
pvr_poly_cxt_col(&cxt,PVR_LIST_TR_POLY);
pvr_poly_compile(&hdr,&cxt);
pvr_prim(&hdr,sizeof(hdr));
vert.argb = PVR_PACK_COLOR(a,r,g,b);
vert.oargb = 0;
vert.flags = PVR_CMD_VERTEX;
vert.x = x-(w/2);
vert.y = y-(h/2);
vert.z = z;
pvr_prim(&vert,sizeof(vert));
vert.x = x+(w/2);
vert.y = y-(h/2);
vert.z = z;
pvr_prim(&vert,sizeof(vert));
vert.x = x-(w/2);
vert.y = y+(h/2);
vert.z = z;
pvr_prim(&vert,sizeof(vert));
vert.x = x+(w/2);
vert.y = y+(h/2);
vert.z = z;
vert.flags = PVR_CMD_VERTEX_EOL;
pvr_prim(&vert,sizeof(vert));
}