Created
May 31, 2024 19:07
-
-
Save avelican/356e464e82da364b60b72cdd02000942 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const w4 = @import("wasm4.zig"); | |
// actual render resolution | |
const SCREEN_SIZE = w4.SCREEN_SIZE; | |
// game resolution (everything is rendered 2x) | |
// const SCREEN_WIDTH = 48*2; | |
const SCREEN_WIDTH = 96; | |
const SCREEN_HEIGHT = SCREEN_SIZE; | |
// const PADDING_X = (SCREEN_SIZE - SCREEN_WIDTH) / 2; | |
const PADDING_X = 32; | |
const SCREEN_START_X = 32; | |
// const SCREEN_END_X = SCREEN_SIZE - PADDING_X; | |
const SCREEN_END_X = 128; | |
//// | |
// const RandomGenerator = struct { | |
// const Self = @This(); | |
// a: u32, | |
// b: u32, | |
// c: u32, | |
// d: u32, | |
// pub fn next(self: *Self) u32 { | |
// self.a &= 0; self.b &= 0; self.c &= 0; self.d &= 0; | |
// var t: u32 = (self.a + self.b) + self.d; | |
// self.d += 1; | |
// self.a = self.b ^ (self.b >> 9); | |
// self.b = self.c + (self.c << 3); | |
// self.c = (self.c << 21) | (self.c >> 11); | |
// self.c += t; | |
// return t; | |
// } | |
// }; | |
// pub fn make_rand(seed: u32) RandomGenerator { | |
// return RandomGenerator { .a = 0x9E3779B9, .b = 0x243F6A88, .c = 0xB7E15162, .d = seed }; | |
// } | |
const SEED = 1337 ^ 0xDEADBEEF; | |
// var rng: RandomGenerator = make_rand(SEED); | |
fn abs(v: i32) i32 { | |
if (v < 0) return -v; | |
return v; | |
} | |
var sponge : u32 = SEED; | |
fn rand () u32 { | |
// sponge *= 7374837; | |
// sponge = @mulWithOverflow(sponge, 7374837); | |
// UGH ZIG | |
// @mulWithOverflow(u64, x, radix, &x); // OBSOLETE EXAMPLE CODE GREAT | |
var wtf = @mulWithOverflow(sponge, 7374837); | |
sponge = wtf[0]; | |
return sponge; | |
} | |
fn rand_range(min: i32, max: i32) i32 { | |
var range = max-min+1; | |
// var ru : u32 = rng.next(); | |
var ru: u32 = rand(); | |
var ri : i32 = @bitCast(ru); | |
// return abs(ri) % range + min; | |
return @mod(abs(ri), range) + min; | |
} | |
fn rand_range2(min: i32, max: i32) i32 { | |
var r : i32 = rand_range(min, max); | |
return nokia_int(r); | |
} | |
fn is_even(n: i32) bool { | |
return @mod(n,2) == 0; | |
} | |
///////////////////////// | |
// fn rectRect(r1: Rect, r2: Rect) bool { | |
// return (r1.x + r1.w >= r2.x && // r1 right edge past r2 left | |
// r1.x <= r2.x + r2.w && // r1 left edge past r2 right | |
// r1.y + r1.h >= r2.y && // r1 top edge past r2 bottom | |
// r1.y <= r2.y + r2.h); // r1 bottom edge past r2 top | |
// } | |
fn rect_rect(x1: i32, y1: i32, w1: i32, h1: i32, x2: i32, y2: i32, w2: i32, h2: i32) bool { | |
return (x1 + w1 >= x2) and // r1 right edge past r2 left | |
(x1 <= x2 + w2) and // r1 left edge past r2 right | |
(y1 + h1 >= y2) and // r1 top edge past r2 bottom | |
(y1 <= y2 + h2); // r1 bottom edge past r2 top | |
} | |
fn rect_rect_fuzzy(_x1: i32, _y1: i32, _w1: i32, _h1: i32, _x2: i32, _y2: i32, _w2: i32, _h2: i32) bool { | |
// zig moment... | |
var x1 = _x1; | |
var y1 = _y1; | |
var w1 = _w1; | |
var h1 = _h1; | |
var x2 = _x2; | |
var y2 = _y2; | |
var w2 = _w2; | |
var h2 = _h2; | |
// // shrink boxes by half | |
// var cx1 = x1 + w1/2; // centerpoints | |
// var cx2 = x2 + w2/2; | |
// var cy1 = y1 + h1/2; | |
// var cy2 = y2 + h2/2; | |
// x1 = cx1 - w1/2; | |
// x2 = cx2 - w2/2; | |
// w1 = w1/2; | |
// w2 = w2/2; | |
// y1 = cy1 - h1/2; | |
// y2 = cy2 - h2/2; | |
// h1 = h1/2; | |
// h2 = h2/2; | |
// wtf is wrong with zig | |
var cx1 = x1 + @divFloor(w1, 2); // centerpoints | |
var cx2 = x2 + @divFloor(w2, 2); | |
var cy1 = y1 + @divFloor(h1, 2); | |
var cy2 = y2 + @divFloor(h2, 2); | |
x1 = cx1 - @divFloor(w1, 2); | |
x2 = cx2 - @divFloor(w2, 2); | |
w1 = @divFloor(w1, 2); | |
w2 = @divFloor(w2, 2); | |
y1 = cy1 - @divFloor(h1, 2); | |
y2 = cy2 - @divFloor(h2, 2); | |
h1 = @divFloor(h1, 2); | |
h2 = @divFloor(h2, 2); | |
return rect_rect(x1, y1, w1, h1, x2, y2, w2, h2); | |
} | |
//////////////////// | |
// note: all sprites have been scaled 2x before import | |
// to comply with the Nokia jam resolution restrictions | |
const skifreeguy_width = 16; | |
const skifreeguy_height = 30; | |
// const skifreeguy_flags = 0; // BLIT_1BPP | |
const skifreeguy_flags = w4.BLIT_1BPP; | |
// const skifreeguy_sprite = [15]u8{ 0xe7,0xe7,0xff,0xc3,0xa5,0xa5,0xe7,0xe7,0x5a,0x5a,0xbd,0xbd,0xdb,0xdb,0xdb }; | |
const skifreeguy_sprite = [60]u8{ 0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xff,0xff,0xff,0xff,0xf0,0x0f,0xf0,0x0f,0xcc,0x33,0xcc,0x33,0xcc,0x33,0xcc,0x33,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0x33,0xcc,0x33,0xcc,0x33,0xcc,0x33,0xcc,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf }; | |
/// | |
pub const tree_tall_width = 24; | |
pub const tree_tall_height = 38; | |
// pub const tree_tall_flags = 1; // BLIT_2BPP | |
pub const tree_tall_flags = w4.BLIT_2BPP; | |
// pub const tree_tall_sprite = [57]u8{ 0x55,0x45,0x55,0x55,0x45,0x55,0x55,0x11,0x55,0x55,0x11,0x55,0x55,0x11,0x55,0x54,0x54,0x55,0x54,0x54,0x55,0x54,0x54,0x55,0x51,0x55,0x15,0x51,0x55,0x15,0x51,0x55,0x15,0x51,0x55,0x15,0x45,0x55,0x45,0x45,0x55,0x45,0x45,0x55,0x45,0x50,0x00,0x15,0x55,0x11,0x55,0x55,0x11,0x55,0x55,0x01,0x5e }; | |
pub const tree_tall_sprite = [228]u8{ 0x55,0x55,0x50,0x55,0x55,0x55,0x55,0x55,0x50,0x55,0x55,0x55,0x55,0x55,0x50,0x55,0x55,0x55,0x55,0x55,0x50,0x55,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x55,0x05,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x50,0x55,0x55,0x55,0x50,0x55,0x55,0x00,0x00,0x00,0x05,0x55,0x55,0x00,0x00,0x00,0x05,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x05,0x05,0x55,0x55,0x55,0x55,0x00,0x05,0x55,0xfa,0x55,0x55,0x00,0x05,0x55,0xfa }; | |
var tree_tall_x : i32 = -100; | |
var tree_tall_y : f32 = -100; | |
// | |
// tree_smol2 | |
pub const tree_smol_width = 16; | |
pub const tree_smol_height = 22; | |
// pub const tree_smol_flags = 0; // BLIT_1BPP | |
pub const tree_smol_flags = w4.BLIT_1BPP; | |
// pub const tree_smol = [11]u8{ 0xe7,0xdb,0xdb,0xbd,0xbd,0x7e,0x7e,0x7e,0x81,0xe7,0xe7 }; | |
// 2x | |
pub const tree_smol_sprite = [44]u8{ 0xfc,0x3f,0xfc,0x3f,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0xc0,0x03,0xc0,0x03,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f,0xfc,0x3f }; | |
var tree_smol_x : i32 = -100; | |
var tree_smol_y : f32 = -100; | |
fn spawn_tree_smol() void { | |
// tree_smol_x = rand_range2( SCREEN_START_X - tree_smol_width, SCREEN_END_X ); | |
tree_smol_x = rand_range2(SCREEN_START_X,128); | |
var y = rand_range2(SCREEN_SIZE, SCREEN_SIZE + 32); | |
tree_smol_y = @floatFromInt(y); | |
} | |
fn spawn_tree_tall() void { | |
tree_tall_x = rand_range2( SCREEN_START_X - tree_tall_width, SCREEN_END_X ); | |
var y = 64 + rand_range2(SCREEN_SIZE, SCREEN_SIZE + 32); | |
tree_tall_y = @floatFromInt(y); | |
} | |
// // // | |
export fn start() void { | |
w4.PALETTE.* = .{ | |
0xc7f0d8, | |
0x43523d, | |
0xff00ff, | |
0x00ffff, | |
}; | |
} | |
var player_x: i32 = SCREEN_SIZE / 2 - skifreeguy_width/2; | |
// var player_y: i32 = SCREEN_SIZE / 2 - skifreeguy_height/2; | |
var player_y: i32 = nokia_int(32 - skifreeguy_height/2); | |
var speed : f32 = 1.3; | |
// var speed : f32 = 20.3; | |
// var speedCounter : i32 = 0; | |
var game_over = false; | |
var whee = false; | |
export fn update() void { | |
if ( ! game_over ) upd(); | |
draw(); | |
} | |
fn upd() void { | |
speed += 0.0005; | |
// input | |
const gamepad = w4.GAMEPAD1.*; | |
if (gamepad & w4.BUTTON_LEFT != 0) { | |
player_x -= 2; | |
} | |
if (gamepad & w4.BUTTON_RIGHT != 0) { | |
player_x += 2; | |
} | |
if (gamepad & w4.BUTTON_DOWN != 0) { | |
speed += 0.01; | |
whee = true; | |
} else { | |
whee = false; | |
} | |
if (player_x <= ( SCREEN_START_X - skifreeguy_width/2) ) { | |
player_x = SCREEN_START_X - skifreeguy_width/2; | |
} | |
if (player_x <= SCREEN_START_X ) { | |
player_x = SCREEN_START_X; | |
} | |
// w4.tracef("%d", player_x); | |
if (player_x >= SCREEN_END_X - skifreeguy_width) { | |
player_x = (SCREEN_END_X - skifreeguy_width ); | |
} | |
// if (gamepad & w4.BUTTON_UP != 0) { | |
// w4.trace("Up button is down!"); | |
// } | |
// update | |
tree_smol_y -= speed; | |
tree_tall_y -= speed; | |
// collide | |
var coll_tree_smol = rect_rect_fuzzy( | |
player_x, | |
player_y, | |
skifreeguy_width, | |
skifreeguy_height, | |
tree_smol_x, | |
nokia_intFromFloat(tree_smol_y), | |
tree_smol_width, | |
tree_smol_height); | |
var coll_tree_tall = rect_rect_fuzzy( | |
player_x, | |
player_y, | |
skifreeguy_width, | |
skifreeguy_height, | |
tree_tall_x, | |
nokia_intFromFloat(tree_tall_y), | |
tree_tall_width, | |
tree_tall_height); | |
if (coll_tree_smol or coll_tree_tall) { | |
game_over = true; | |
whee = false; // :( | |
} | |
} | |
fn draw() void { | |
// left padding | |
w4.rect(0, 0, PADDING_X, SCREEN_SIZE); | |
// rightp adding | |
w4.rect(SCREEN_END_X, 0, PADDING_X, SCREEN_SIZE); | |
w4.DRAW_COLORS.* = 2; // TODO what is this | |
// if (tmp_y > SCREEN_SIZE) tmp_y = 0; | |
// const gamepad = w4.GAMEPAD1.*; | |
// if (gamepad & w4.BUTTON_1 != 0) { | |
// w4.DRAW_COLORS.* = 4; | |
// } | |
if (tree_smol_y <= (-tree_smol_height)) spawn_tree_smol(); | |
if (tree_tall_y <= (-tree_tall_height)) spawn_tree_tall(); | |
w4.blit(&tree_smol_sprite, tree_smol_x, nokia_intFromFloat(tree_smol_y), tree_smol_width, tree_smol_height, tree_smol_flags); | |
w4.blit(&tree_tall_sprite, tree_tall_x, nokia_intFromFloat(tree_tall_y), tree_tall_width, tree_tall_height, tree_tall_flags); | |
w4.blit(&skifreeguy_sprite, player_x, player_y, skifreeguy_width, skifreeguy_height, skifreeguy_flags); | |
if ( whee ) { | |
w4.text("wheee!", player_x - 15, player_y - 12); | |
// w4.tone (frequency, duration, volume, flags); | |
w4.tone (220, 2, 10, w4.TONE_MODE3); | |
} | |
w4.text("SCORE", SCREEN_SIZE/2 - 8 * 4, SCREEN_SIZE - 20 ); | |
draw_number(@intFromFloat(speed * 1000), SCREEN_SIZE/2 - 8*4, SCREEN_SIZE-10); | |
if (game_over) { | |
w4.text("GAME OVER", SCREEN_SIZE/2-34, SCREEN_SIZE/2); | |
w4.text("PRESS R TO", SCREEN_SIZE/2-38, SCREEN_SIZE/2 + 16); | |
w4.text(" RESTART", SCREEN_SIZE/2-34, SCREEN_SIZE/2 + 24); | |
} | |
} | |
fn num_digits(_num: i32) i32 { | |
var num = _num; | |
var digits : i32 = 1; | |
while(true) { | |
if (num < 10) { | |
return digits; | |
} | |
digits += 1; | |
// num = num / 10; | |
num = @divFloor(num, 10); | |
} | |
} | |
fn draw_number(_num: i32, x_start: i32, y: i32) void { | |
var num = _num; | |
const CHAR_WIDTH = 8; | |
var x = x_start + num_digits(num) * CHAR_WIDTH; | |
while(true) { | |
var digit = @mod(num, 10); | |
draw_digit(digit, x, y); | |
x -= CHAR_WIDTH; | |
if (num < 10) { return; } | |
num = @divFloor(num, 10); | |
} | |
} | |
fn draw_digit(num: i32, x: i32, y: i32) void { | |
switch(num) { | |
0 => { w4.text("0", x, y); }, | |
1 => { w4.text("1", x, y); }, | |
2 => { w4.text("2", x, y); }, | |
3 => { w4.text("3", x, y); }, | |
4 => { w4.text("4", x, y); }, | |
5 => { w4.text("5", x, y); }, | |
6 => { w4.text("6", x, y); }, | |
7 => { w4.text("7", x, y); }, | |
8 => { w4.text("8", x, y); }, | |
9 => { w4.text("9", x, y); }, | |
else => { w4.text("",0,0); } | |
} | |
} | |
fn nokia_intFromFloat(f: f32) i32 { | |
var i : i32 = @intFromFloat(f); | |
return nokia_int(i); | |
} | |
fn nokia_int(i: i32) i32 { | |
if ( is_even(i) ) { | |
return i; | |
} else { | |
return i - 1; | |
} | |
} | |
// ////// | |
// /// | |
// /// crap the font will get me disqualified | |
// /// pray to god this works | |
// const fontWidth = 208; | |
// const fontFlags = w4.BLIT_1BPP; | |
// const charWidth = 8; | |
// const charHeight = 8; | |
// const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
// const font = [_]u8{ | |
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
// 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x3c, 0x18, 0x3e, | |
// 0x1c, 0x26, 0x10, 0x2c, 0x12, 0x08, 0x24, 0x26, | |
// 0x1c, 0x3c, 0x1c, 0x78, 0x1c, 0x3c, 0x62, 0x42, | |
// 0x82, 0xc4, 0x42, 0x66, 0x08, 0x32, 0x22, 0x52, | |
// 0x24, 0x51, 0x22, 0x25, 0x28, 0x14, 0x14, 0x08, | |
// 0x24, 0x26, 0x22, 0x52, 0x22, 0xa4, 0x22, 0x52, | |
// 0x22, 0xa5, 0x44, 0x2a, 0x24, 0x1c, 0x14, 0x52, | |
// 0x20, 0x12, 0x20, 0x10, 0x20, 0x26, 0x28, 0x04, | |
// 0x14, 0x08, 0x2c, 0x24, 0x22, 0x52, 0x22, 0xa4, | |
// 0x20, 0x10, 0x22, 0x24, 0x54, 0x10, 0x24, 0x04, | |
// 0x14, 0x5c, 0x40, 0x22, 0x38, 0x38, 0x4e, 0x7c, | |
// 0x28, 0x08, 0x28, 0x10, 0x54, 0x58, 0x42, 0x14, | |
// 0x44, 0x78, 0x18, 0x10, 0x24, 0x28, 0x54, 0x10, | |
// 0x14, 0x08, 0x24, 0xa4, 0x40, 0x62, 0x40, 0x20, | |
// 0x44, 0x48, 0x10, 0x08, 0x34, 0x30, 0x54, 0x48, | |
// 0x44, 0x20, 0x54, 0x48, 0x04, 0x20, 0x44, 0x28, | |
// 0x2c, 0x28, 0x08, 0x10, 0x3c, 0xa4, 0x42, 0xa4, | |
// 0x44, 0xa0, 0x44, 0xc9, 0x10, 0x48, 0x24, 0x52, | |
// 0x44, 0x4a, 0x44, 0xa0, 0x3a, 0x48, 0x44, 0xa0, | |
// 0x44, 0x10, 0x28, 0xa8, 0x48, 0x38, 0x42, 0x5b, | |
// 0x3c, 0x58, 0x38, 0x40, 0x38, 0x46, 0x68, 0x34, | |
// 0x42, 0x2c, 0x82, 0x84, 0x3a, 0x40, 0x08, 0x86, | |
// 0x38, 0x40, 0x3a, 0x10, 0x48, 0x46, 0x30, 0x66 | |
// }; | |
// fn drawSpace(x: i32, y: i32, column: i32, line: i32, colors: u16) void { | |
// // store<u16>(w4.DRAW_COLORS, w4.DRAW_COLORS & 0x0F); | |
// w4.DRAW_COLORS.* = w4.DRAW_COLORS.* & 0x0F; | |
// w4.rect( | |
// x + (column * charWidth), | |
// y + (line * charHeight), | |
// charWidth, | |
// charHeight | |
// ); | |
// // store<u16>(w4.DRAW_COLORS, colors); | |
// w4.DRAW_COLORS.* = colors; | |
// } | |
// fn w4.text(str: []const u8, x: i32, y: i32) void { | |
// // write(str, x, y, 0x11); | |
// write(str, x, y, 0x10); | |
// w4.DRAW_COLORS.* = 2; | |
// } | |
// fn write(text: []const u8, x: i32, y: i32, colors: u16) void { | |
// // Set draw colors... | |
// // store<u16>(w4.DRAW_COLORS, colors); | |
// w4.DRAW_COLORS.* = colors; | |
// // Line and column counters. | |
// var line : i32 = 0; | |
// var column: i32 = 0; | |
// // Iterate through each character... | |
// // for(var i = 0; i < text.length; i += 1) { | |
// var i : usize = 0; | |
// while(true) { // zig's for loops are confusing | |
// w4.trace("AAAA"); | |
// if (i >= text.len) break; | |
// w4.trace("BBBB"); | |
// // const char: string = text.charAt(i); | |
// // const charCode: i32 = char.charCodeAt(0); | |
// const char = text[i]; | |
// const charCode = text[i]; | |
// // w4.tracef("%c", char); | |
// w4.trace("CCCC"); | |
// // Break into next line when encounter a "\n" (newline)... | |
// if(charCode == 10) { | |
// line += 1; | |
// column = 0; | |
// i+=1; | |
// continue; | |
// } | |
// w4.trace("DDDD"); | |
// // Character index on charset. | |
// // var charIndex: i32 = charset.indexOf(char); | |
// var charIndex = char-65; | |
// // Skip invalid characters, spaces, etc. | |
// if( (charIndex < 0) or (charIndex >= charset.len)) { | |
// w4.trace("EEEEE"); | |
// drawSpace(x, y, column, line, colors); | |
// column += 1; | |
// i+=1; | |
// w4.trace("EEEEE"); | |
// continue; | |
// } | |
// w4.trace("FFFF"); | |
// // Draw character... | |
// w4.blitSub( | |
// &font, | |
// x + (column * charWidth), | |
// y + (line * charHeight), | |
// charWidth, | |
// charHeight, | |
// charIndex * charWidth, | |
// 0, | |
// fontWidth, | |
// fontFlags | |
// ); | |
// // Advance to next column... | |
// column += 1; | |
// i += 1; | |
// } | |
// } | |
// // export function update (): void { | |
// // write("HELLO WORLD WITH\nOUR CUSTOM FONT", 4, 4, 0x30); | |
// // } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Quite Incredible.
11/10