Platforms_lesson_ipynb_2_
layout: post title: Mario Platforms Lesson description: A lesson designed to help you create your own platform for your game courses: { csse: {week: 8 } } type: ccc author: Gavin Copley, Zafeer Ahmed, Ryan Nguyen —
Using OOP
We use Object Orientated Programming to complete this task. OOP uses objects, classes, variables, and includes a plethora of other items to create, in this case, a developed and fully functional javascript game! Follow along as we go through the steps to make 3 of the following additions: A platform, a coin.
What do we expect?
We want the platform to be able to be walked on, we want to be able to jump off of it and jump onto it. We also want a coin to that can have collision with the player.
Step 1: Making A Platform Class
First, we need to make a new .js file to store our information. We named ours PlatformO.js, but you can name it whatever you want. However, if you do that, make sure you reference the correct file name when trying to import it (not recommended).
- Include the following code to make sure that it runs with the rest of the game:
import GameEnv from './GameEnv.js';
import GameObject from './GameObject.js';
export class PlatformO extends GameObject {
constructor(canvas, image) {
super(canvas, image, 0);
}
// Required, but no update action
update() {
}
// Draw position is always 0,0
draw() {
this.ctx.drawImage(this.image, 0, 0);
}
// Set platform position
size() {
// Formula for Height should be on constant ratio, using a proportion of 832
const scaledHeight = GameEnv.innerHeight * (60/832);
// Formula for Width is scaled: scaledWidth/scaledHeight == this.width/this.height
const scaledWidth = 150;
const platformX = .1 * GameEnv.innerWidth;
const platformY = (GameEnv.bottom - scaledHeight) - 150;
// set variables used in Display and Collision algorithms
this.bottom = platformY;
this.collisionHeight = scaledHeight;
this.collisionWidth = scaledWidth;
//this.canvas.width = this.width;
//this.canvas.height = this.height;
this.canvas.style.width = `${scaledWidth}px`;
this.canvas.style.height = `${scaledHeight}px`;
this.canvas.style.position = 'absolute';
this.canvas.style.left = `${platformX}px`;
this.canvas.style.top = `${platformY}px`;
}
}
export default PlatformO;
This code is very similar to the tube code. The PlatformO class is extending the GameObject class, and after being defined, we can now change values and key features that are needed from a platform.
Constructor initializes the class and super inherits the traits from the class that it is extending. Draw draws it on the canvas and size adjusts values like position, height, and width.
There are many files in which we need to make changes so the game is aware of the platform. Namely, the md file that the game is being displayed in, Player.js so we can have the player collide and stand on the platform, and also some code in GameLevel.
- Most of the values are in this code is changeable; we can change the position, size, and so on for the platform. Be sure to experiment!
Lets make the platform have an image. Lets navigate to the file named “2023-11-27-CSSE-oop-game-levels.md” or whatever you named your main file that holds the game. The following code is needed to provide an image for the platform (image is in slack)
var assets = {
// other stuff up
platformO: {
grass: { src: "/images/brick_wall.png" },
},
// other stuff down
};
Scroll down to find and add to the next part…
new GameLevel( {
tag: "hills",
background: assets.backgrounds.hills,
platform: assets.platforms.grass,
platformO: assets.platformO.grass, // This is what we need to add
player: assets.players.mario,
tube: assets.obstacles.tube,
callback: testerCallBack,
thing: assets.thing.coin,
} );
Now we need to edit the GameLevel.js file. This will make the platform constructed with the image when the level starts.
constructor(gameObject) {
// conditional assignments from GameObject to instance variables
this.tag = gameObject?.tag;
this.backgroundImg = gameObject.background?.file;
this.platformImg = gameObject.platform?.file;
this.platformOImg = gameObject.platformO?.file; // You want to add this one!
this.thingImg = gameObject.thing?.file;
this.playerImg = gameObject.player?.file;
this.playerData = gameObject?.player;
this.tubeImg = gameObject.tube?.file;
this.isComplete = gameObject?.callback; // function that determines if level is complete
GameEnv.levels.push(this);
}
Scroll down and add this too
const imagesToLoad = [];
// other stuff
if (this.platformOImg) {
imagesToLoad.push(this.loadImage(this.platformOImg));
}
Make sure you have this!
This code is mandatory for the platform to be displayed! This code is all based off of Mr. Mortensen’s previous code and uses his code as an example.
Step 2: Adding Collision
Next, we are going to be adding collision to the platform. To do this, we have to go into Player.js and add code for collision for the platform so the character can stand on it.
We need to add the following code next to the tube collision:
if (this.collisionData.touchPoints.other.id === "jumpPlatform") {
// Collision with the left side of the Platform
console.log("id")
if (this.collisionData.touchPoints.other.left && (this.topOfPlatform === true)) {
this.movement.right = false;
console.log("a")
}
// Collision with the right side of the platform
if (this.collisionData.touchPoints.other.right && (this.topOfPlatform === true)) {
this.movement.left = false;
console.log("b")
}
// Collision with the top of the player
if (this.collisionData.touchPoints.this.ontop) {
this.gravityEnabled = false;
console.log("c")
}
if (this.collisionData.touchPoints.this.bottom) {
this.gravityEnabled = false;
console.log("d")
}
if (this.collisionData.touchPoints.this.top) {
this.gravityEnabled = false;
this.topOfPlatform = true;
console.log(this.topOfPlatform + "top")
console.log(this.gravityEnabled + "grav")
//console.log("e");
}
}
Make sure to have the following code to the else statement below the previous code
this.topOfPlatform = false;
this.movement.left = true;
this.movement.right = true;
this.movement.down = true;
this.gravityEnabled = true;
These 2 pieces of code both affect the collision of the player with the platform. We are using Mr Mortensen’s collisionData.touchPoints and using it to detect collision with the platform.
This is the complete code for the platform. Be sure to ask me anything if you need extra help or if anything is unclear.
The next thing we added to our game was the coin, which we will attempt to allow you to reload the page once you touch it.
- Make sure you have the coin.png downloaded*
- The first thing we are going to do is locate the JS files in platformer, and create one (which we called Thing1 for simplicity, but you can call it Coin.js)
Adding the coin png
*These first few steps will be a repeat, but necessary for the coin to show up in the game
Locate the CSSE-oop game level md file
// Define assets for the game
var assets = {
...Previous code
thing: {
coin: { src: "/images/Coin.png" } //Add this one!
},
platformO: {
grass: { src: "/images/brick_wall.png" },
},
We called our group “thing” but you can call it whatever you want. We defined the image as coin and then pasted the image source.
// Game screens
new GameLevel( {tag: "hills", background: assets.backgrounds.hills, platform: assets.platforms.grass,
platformO: assets.platformO.grass, player: assets.players.mario, tube: assets.obstacles.tube,
callback: testerCallBack, thing: assets.thing.coin, } ); // <-- add the line thing: assets.thing.con
Again, your code will differ from ours if you didn’t name it “Thing”
Next thing we want you to do is
- Just like the platfrom, make a new .js file and call it thing.js
import GameEnv from './GameEnv.js';
import GameObject from './GameObject.js';
export class Thing1 extends GameObject {
constructor(canvas, image) {
super(canvas, image, 0);
// Set the initial position and size
this.size();
}
// Required, but no update action
update() {
}
// Draw position is always 0,0
draw() {
// Save the current transformation matrix
this.ctx.save();
// Rotate the canvas 90 degrees to the left
this.ctx.rotate(-Math.PI / 2);
// Draw the image at the rotated position (swap x and y)
this.ctx.drawImage(this.image, -this.image.height, 0);
// Restore the original transformation matrix
this.ctx.restore();
}
// Center and set Thing1 position with adjustable height and width
size() {
// Make the image 10 times smaller
const scaledWidth = this.image.width * 0.2;
const scaledHeight = this.image.height * 0.169;
// Center the object on the screen
const randomPosition = Math.random() < 0.5; // Randomly choose between two positions
let thingX, thingY;
if (randomPosition) {
thingX = (GameEnv.innerWidth - scaledWidth) / 2.5;
thingY = (GameEnv.innerHeight - scaledHeight) / 1.01;
} else {
thingX = (GameEnv.innerWidth - scaledWidth) / 7.5;
thingY = (GameEnv.innerHeight - scaledHeight) / 2.02;
}
// Set variables used in Display and Collision algorithms
this.bottom = thingY + scaledHeight;
this.collisionHeight = scaledHeight;
this.collisionWidth = scaledWidth;
this.canvas.style.width = `${scaledWidth}px`;
this.canvas.style.height = `${scaledHeight}px`;
this.canvas.style.position = 'absolute';
this.canvas.style.left = `${thingX}px`;
this.canvas.style.top = `${thingY}px`;
}
}
export default Thing1;
import GameEnv from './GameEnv.js';
import GameObject from './GameObject.js';
export class Thing1 extends GameObject {
constructor(canvas, image) {
super(canvas, image, 0);
// Set the initial position and size
this.size();
}
// Required, but no update action
update() {
}
// Draw position is always 0,0
draw() {
// Save the current transformation matrix
this.ctx.save();
// Rotate the canvas 90 degrees to the left
this.ctx.rotate(-Math.PI / 2);
// Draw the image at the rotated position (swap x and y)
this.ctx.drawImage(this.image, -this.image.height, 0);
// Restore the original transformation matrix
this.ctx.restore();
}
// Center and set Thing1 position with adjustable height and width
size() {
// Make the image 10 times smaller
const scaledWidth = this.image.width * 0.2;
const scaledHeight = this.image.height * 0.169;
// Center the object on the screen
const randomPosition = Math.random() < 0.5; // Randomly choose between two positions
let thingX, thingY;
if (randomPosition) {
thingX = (GameEnv.innerWidth - scaledWidth) / 2.5;
thingY = (GameEnv.innerHeight - scaledHeight) / 1.01;
} else {
thingX = (GameEnv.innerWidth - scaledWidth) / 7.5;
thingY = (GameEnv.innerHeight - scaledHeight) / 2.02;
}
// Set variables used in Display and Collision algorithms
this.bottom = thingY + scaledHeight;
this.collisionHeight = scaledHeight;
this.collisionWidth = scaledWidth;
this.canvas.style.width = `${scaledWidth}px`;
this.canvas.style.height = `${scaledHeight}px`;
this.canvas.style.position = 'absolute';
this.canvas.style.left = `${thingX}px`;
this.canvas.style.top = `${thingY}px`;
}
// Method to shrink the coin
shrinkCoin() {
// Set variables used in Display and Collision algorithms
const scaledWidth = 0; // Set width to 0
const scaledHeight = 0; // Set height to 0
this.bottom = 0;
this.collisionHeight = 0;
this.collisionWidth = 0;
this.canvas.style.width = `${scaledWidth}px`;
this.canvas.style.height = `${scaledHeight}px`;
}
}
export default Thing1;
Let’s break it down
var assets = {
// other stuff up
thing: {
coin: { src: "/images/Coin.png" }
},
// other stuff down
};
new GameLevel( {
tag: "hills",
background: assets.backgrounds.hills,
platform: assets.platforms.grass,
platformO: assets.platformO.grass,
player: assets.players.mario,
tube: assets.obstacles.tube,
callback: testerCallBack,
thing: assets.thing.coin, // Insert coin
} );
constructor(gameObject) {
// conditional assignments from GameObject to instance variables
this.tag = gameObject?.tag;
this.backgroundImg = gameObject.background?.file;
this.platformImg = gameObject.platform?.file;
this.platformOImg = gameObject.platformO?.file;
this.thingImg = gameObject.thing?.file; // Insert coin
this.playerImg = gameObject.player?.file;
this.playerData = gameObject?.player;
this.tubeImg = gameObject.tube?.file;
this.isComplete = gameObject?.callback; // function that determines if level is complete
GameEnv.levels.push(this);
}
const imagesToLoad = [];
// other stuff
if (this.platformOImg) {
imagesToLoad.push(this.loadImage(this.platformOImg));
}
Your Homework!
For homework we want you to complete both of these or just one and something unique and creative
- Make the coin disappear after touching it. The coin collision is given.
- Make some more platforms to jump on