-
Leanna Mi N. authored
Added Start Scene (used scenemanager.js library which utilizes namespacing so things are just a lil bit different. BTW sketch.js is now game.js in gamejs/
4662ffed
game.js 17.29 KiB
function Game() {
// Current Sprite Selection from User -- might not be needed
let currUserSprite;
// Four numbers that define the transform, i hat and j hat
const i_x = 1;
const i_y = 0.5;
const j_x = -1;
const j_y = 0.5;
// Symmetric 2D array to store instances of TileClass
const tile_arr_size = 12;
let tileArr = new Array(tile_arr_size).fill(null).map(() => new Array(tile_arr_size).fill(null));
let playerSprite;
let playerSprite_curTgc; // the current tgc coordinates that the player is at
let playerSprite_curTileType; // The tile type that the player is currently sitting on
// Sprite size
const w = 64;
const h = 64;
// what the current cursor calculation is based off
let maxWinWidth = 1920;
let maxWinHeight = 1080;
// TODO: replace
let tools = ["Fix Sidewalk", "Add Curb Ramp"];
let currentToolIndex = 0; // keyPressed() has logic to make sure that index doens't go outisde of tools array bounds
/*
0 --> grass block (use for where houses go for now)
1 --> road tile
2 --> sidewalk tile
3 --> sidewalk rotated 180 degrees
4 --> broken sidewalk
5 --> broken sidewalk rotated 180 degrees
6 --> sidewalk corner topLeft (no curb ramp)
7 --> sidewalk corner botLeft (no curb ramp)
8 --> sidewalk corner botRight (no curb ramp)
9 --> sidewalk corner topRight (no curb ramp)
*/
// Hardcoding tile placement for the first level
// x and y here are just the grid coordinates
const startingTileIndex = {
x: 3,
y: 0
};
const endingTileIndex = {
x: 3,
y: 11
};
const levelOne = [
[0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0],
[0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0],
[0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0],
[3, 3, 5, 6, 1, 1, 1, 1, 9, 3, 5, 3],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[3, 5, 3, 7, 1, 1, 1, 1, 8, 3, 3, 3],
[0, 0, 0, 2, 1, 1, 1, 1, 4, 0, 0, 0],
[0, 0, 0, 2, 1, 1, 1, 1, 4, 0, 0, 0],
[0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0],
]; // Currently 10 by 10
this.setup = function() {
// createCanvas(maxWinWidth, maxWinHeight);
new Canvas(maxWinWidth, maxWinHeight);
imageMode(CENTER);
// Create our player sprite
playerSprite = new Sprite();
playerSprite.width = w;
playerSprite.height = h;
playerSprite.image = 'assets/tile_pngs/grass.png';
playerSprite_curTgc = startingTileIndex; // An object: {x: _, y: _}
playerSprite.x = toScreenCoords(playerSprite_curTgc).x;
playerSprite.y = toScreenCoords(playerSprite_curTgc).y;
// Now loop through our tile map and draw
// each tile accoridng to our levelOne matrix
// mapping
for (let i = 0; i < tile_arr_size; i++) {
for (let j = 0; j < tile_arr_size; j++) {
let tile_type = levelOne[i][j];
let tsc = toScreenCoords({
x: i,
y: j
});
switch (tile_type) {
case 0: // grass block (use for where houses go for now)
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "city", "none");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, grassTile, "decoration", "normal");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 1: // road tile
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "vertical");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, roadTile, "road", "normal");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 2: // sidewalk tile
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "horizontal");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalk, "sidewalk", "normal");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 3: // sidewalk rotated 180 degrees
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkRotated180, "sidewalk", "rotated180");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 4: // broken sidewalk
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkBroken, "broken_sidewalk", "normal");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 5: // broken sidewalk rotated 180 degrees
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkBrokenRotated180, "broken_sidewalk", "rotated180");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 6: // sidewalk corner topLeft (no curb ramp)
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkCornerTopLeft, "sidewalk_corner", "normal");
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 7: // sidewalk corner botLeft (no curb ramp)
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkCornerBotLeft, "sidewalk_corner", "rotated90"); // TODO: Replace with rotated versions
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 8: // sidewalk corner botRight (no curb ramp)
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkCornerBotRight, "sidewalk_corner", "rotated180"); // TODO: Replace with rotated versions
tileArr[i][j].display(tileArr[i][j].sprite);
break;
case 9: // sidewalk corner topRight (no curb ramp)
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "road", "4way");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, sidewalkCornerTopRight, "sidewalk_corner", "rotated270"); // TODO: Replace with rotated versions
tileArr[i][j].display(tileArr[i][j].sprite);
break;
default:
// Otherwise, default to road
// grid[i][j] = new GridTile(j * gridSize, i * gridSize, gridSize, "city", "none");
tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, roadTile, "road", "normal");
tileArr[i][j].display(tileArr[i][j].sprite);
}
// tileArr[i][j] = new TileClass(i, j, tsc.x, tsc.y, roadTile);
// tileArr[i][j].display(tileArr[i][j].sprite);
}
}
}
this.draw = function() {
currUserSprite = sidewalk;
background('#588dbe');
translate(width / 2, height / 3);
// For now, use simple text to show which
// tool you have selected
// Top-left corner
// textAlign(LEFT, TOP);
textSize(16);
// fill(255);
// stroke(0);
// strokeWeight(4);
text(`Current Tool: ${tools[currentToolIndex]}`, -300, -10);
// Draw the player in their current pos
let curPlayerScreenCords = toScreenCoords(playerSprite_curTgc);
playerSprite.x = curPlayerScreenCords.x;
playerSprite.y = curPlayerScreenCords.y;
let tgc = screenToGridCoords({
x: mouseX,
y: mouseY
});
for (let i = 0; i < tile_arr_size; i++) {
for (let j = 0; j < tile_arr_size; j++) {
tileArr[i][j].display(tileArr[i][j].sprite);
// hover highlighting
if (tgc.x == i && tgc.y == j && tileArr[i][j].sprite == roadTile) {
tileArr[i][j].display(roadHighlightedTile);
} else {
tileArr[i][j].display(tileArr[i][j].sprite);
}
}
}
}
this.mouseClicked = function() {
let {
x: tgc_x,
y: tgc_y
} = screenToGridCoords({
x: mouseX,
y: mouseY
});
if (!isValidGridCoords(tgc_x, tgc_y)) {
return;
}
/* Type can either be
- decoration (grass, house, etc)
- road
- sidewalk
- broken_sidewalk
- sidewalk_corner
- sidewalk_corner_curbRamp
*/
/* Orientation can either be
- normal (rotated 0 degrees)
- rotated90
- rotated180
- rotated270
*/
// TODO: Make a fixed_sidewalk sprite
tile_type = tileArr[tgc_x][tgc_y].type;
tile_orientation = tileArr[tgc_x][tgc_y].orientation;
// Depending on what type of tile you clicked on,
// update the sprite accordingly
if (tile_type === "broken_sidewalk" && tools[currentToolIndex] === "Fix Sidewalk") {
// If broken sidewalk is clicked, then
// repair to make fixed sidewalk
updateTileType(tgc_x, tgc_y, "sidewalk");
// Check to see this tile's orientation to make sure we
// place down the right sprite
if (tile_orientation === "normal") {
updateTileSprite(tgc_x, tgc_y, sidewalk);
} else if (tile_orientation === "rotated180") {
updateTileSprite(tgc_x, tgc_y, sidewalkRotated180);
}
} else if (tile_type === "sidewalk_corner" && tools[currentToolIndex] === "Add Curb Ramp") {
// If sidewalk corner is clicked, then
// replace with curb ramp
updateTileType(tgc_x, tgc_y, "sidewalk_corner_curbRamp");
// Check to see this tile's orientation to make sure we
// place down the right sprite
if (tile_orientation === "normal") {
updateTileSprite(tgc_x, tgc_y, sidewalkCurbRampTopLeft);
} else if (tile_orientation === "rotated90") {
updateTileSprite(tgc_x, tgc_y, sidewalkCurbRampBotLeft);
} else if (tile_orientation === "rotated90") {
updateTileSprite(tgc_x, tgc_y, sidewalkCurbRampBotRight);
} else {
updateTileSprite(tgc_x, tgc_y, sidewalkCurbRampTopRight);
}
}
}
this.keyPressed = function() {
if (key === 'r') {
tileArr = rotateMatrixClockwise(tileArr);
}
if (key === 't') {
// Cycle to the next tool in our tools array (and wrap back around if
// we have reached the end of our tools array)
currentToolIndex = (currentToolIndex + 1) % tools.length;
// TODO: Change the cursor to an image that matches the current tool
// type can either be predefined image or path to image
// cursor(type, x, y)
}
}
this.keyReleased = function() {
// why is the player not showing up?
// it seems to be a reference issue
let playerSprite_newTcgCords_x = playerSprite_curTgc.x;
let playerSprite_newTcgCords_y = playerSprite_curTgc.y;
if (key === 'w') {
playerSprite_newTcgCords_y -= 1;
} else if (key === 's') {
playerSprite_newTcgCords_y += 1;
} else if (key === 'a') {
playerSprite_newTcgCords_x -= 1;
} else if (key === 'd') {
playerSprite_newTcgCords_x += 1;
}
// Check to make sure that the new coords are valid, if not, then don't
// allow the player to move to that tile
let tileType_playerIsOn = tileArr[playerSprite_curTgc.x][playerSprite_curTgc.y].type;
let tileType_nextTile = tileArr[playerSprite_newTcgCords_x][playerSprite_newTcgCords_y].type;
// console.log(`\nCurrent tile: ${tileType_playerIsOn}`);
// console.log(`Next tile: ${tileType_nextTile}`);
// console.log(`tileType_nextTile !== "broken_sidewalk": ${tileType_nextTile !== "broken_sidewalk"}`);
// console.log(`tileType_nextTile !== "grass": ${tileType_nextTile !== "grass"}`);
// console.log(`(tileType_nextTile !== "road" && tileType_playerIsOn !== "sidewalk_corner") : ${(tileType_nextTile !== "road" && tileType_playerIsOn !== "sidewalk_corner") }`);
// console.log(`(tileType_nextTile !== "sidewalk_corner" && tileType_playerIsOn !== "road"): ${(tileType_nextTile !== "sidewalk_corner" && tileType_playerIsOn !== "road")}`);
// console.log(`(tileType_nextTile !== "sidewalk" && tileType_playerIsOn !== "road"): ${(tileType_nextTile !== "sidewalk" && tileType_playerIsOn !== "road")}`);
// check redundancy later here
if (tileType_nextTile == "road" && tileType_playerIsOn == "sidewalk_corner_curbRamp") {
playerSprite_curTgc.x = playerSprite_newTcgCords_x;
playerSprite_curTgc.y = playerSprite_newTcgCords_y;
return;
}
if (tileType_nextTile == "sidewalk_corner_curbRamp" && tileType_playerIsOn == "road") {
playerSprite_curTgc.x = playerSprite_newTcgCords_x;
playerSprite_curTgc.y = playerSprite_newTcgCords_y;
return;
}
if (tileType_nextTile == "road" && tileType_playerIsOn == "road") {
playerSprite_curTgc.x = playerSprite_newTcgCords_x;
playerSprite_curTgc.y = playerSprite_newTcgCords_y;
return;
}
if (tileType_nextTile == "sidewalk_corner_curbRamp") {
playerSprite_curTgc.x = playerSprite_newTcgCords_x;
playerSprite_curTgc.y = playerSprite_newTcgCords_y;
return;
}
// I think we only want to walk on sidwalk no?
if (tileType_playerIsOn != "road" &&
(tileType_nextTile == "sidewalk" || tileType_nextTile == "sidewalk_corner")) {
console.log("The movement has been allowed...");
playerSprite_curTgc.x = playerSprite_newTcgCords_x;
playerSprite_curTgc.y = playerSprite_newTcgCords_y;
}
}
function rotateMatrixClockwise(matrix) {
let rotatedMatrix = new Array(tile_arr_size).fill(null).map(() => new Array(tile_arr_size).fill(null));
for (let i = 0; i < tile_arr_size; i++) {
for (let j = 0; j < tile_arr_size; j++) {
let newX = j;
let newY = tile_arr_size - 1 - i;
let tile = matrix[i][j];
let screenCoord = toScreenCoords({
x: newX,
y: newY
});
rotatedMatrix[newX][newY] = new TileClass(newX, newY, screenCoord.x, screenCoord.y, tile.sprite);
}
}
return rotatedMatrix;
}
// Helper function to check if grid coordinates are within bounds
function isValidGridCoords(tgc_x, tgc_y) {
return tgc_x >= 0 && tgc_x < tile_arr_size && tgc_y >= 0 && tgc_y < tile_arr_size;
}
// Helper function to update tile sprite
function updateTileSprite(tgc_x, tgc_y, sprite) {
tileArr[tgc_x][tgc_y].sprite = sprite;
}
// Helper function to update tile type
function updateTileType(tgc_x, tgc_y, type) {
tileArr[tgc_x][tgc_y].type = type;
}
function invertMatrix(a, b, c, d) {
/*
Invert a 2d matrix, with a, b, c, and d being
[ a b ]
[ c d ]
*/
const det = (1 / (a * d - b * c));
return {
a: det * d,
b: det * -b,
c: det * -c,
d: det * a,
}
}
function toGridCoords(screen) {
const a = i_x * 0.5 * w;
const b = j_x * 0.5 * w;
const c = i_y * 0.5 * h;
const d = j_y * 0.5 * h;
const inv = invertMatrix(a, b, c, d);
return {
// offset mouse cursor to align with block
x: screen.x * inv.a + screen.y * inv.b - 25.75,
y: screen.x * inv.c + screen.y * inv.d + 4.15,
}
}
function toScreenCoords(tile) {
return {
x: tile.x * i_x * 0.5 * w + tile.y * j_x * 0.5 * w,
y: tile.x * i_y * 0.5 * h + tile.y * j_y * 0.5 * h,
}
}
// Helper function to convert screen coordinates to grid coordinates
function screenToGridCoords(screen) {
let tgc = toGridCoords(screen);
return {
x: Math.floor(tgc.x),
y: Math.floor(tgc.y)
};
}
}