Skip to content

Commit

Permalink
added mario v2.0 to the repository and ported over some changes from …
Browse files Browse the repository at this point in the history
…v1.0
  • Loading branch information
DanielFitzwilliam committed Jan 11, 2024
1 parent 94cff90 commit a3075f9
Show file tree
Hide file tree
Showing 23 changed files with 2,228 additions and 2 deletions.
107 changes: 107 additions & 0 deletions 2024-01-08-CSSE-oop-game-levels2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
layout: base
title: Dynamic Game Levels v2.0
description: Incorporate student lessons goombas, platforms, parallax backgrounds, settings with local storage, etc. Refactor code introducing GameSetup and SettingsControl. Style is moved into _sass.
type: collab
courses: { csse: {week: 18} }
image: /images/platformer/backgrounds/hills.png
---

<!-- Syle is now located, as of Jan 2024 v2.0, in _sass/minima/platformer-styles.scss -->

<!-- DOM Settings Panel (sidebar id and div), managed by SettingsContro.js -->
<div id="sidebar" class="sidebar">
<a href="javascript:void(0)" id="sidebar-header">&times; Settings</a>
</div>

<!-- Wrap both the controls and gameplay in a container div -->
<div id="canvasContainer">
<div class="submenu">
<div id="score">
Timer: <span id="timeScore">0</span>
</div>
<div id="gameBegin" hidden>
<button id="startGame">Start Game</button>
</div>
<div id="gameOver" hidden>
<button id="restartGame">Restart</button>
</div>
<div id="settings"> <!-- Controls -->
<!-- Background controls -->
<button id="settings-button">Settings</button>
</div>
<div id="leaderboard"> <!-- Controls -->
<button id="leaderboard-button">Leaderboard</button>
</div>
</div>
<!-- JavaScript-generated canvas items are inserted here -->
</div>

<script type="module">
// Imports to drive game
import GameSetup from '{{site.baseurl}}/assets/js/platformer2/GameSetup.js';
import GameControl from '{{site.baseurl}}/assets/js/platformer2/GameControl.js';
import SettingsControl from '{{site.baseurl}}/assets/js/platformer2/SettingsControl.js';
import GameEnv from '{{site.baseurl}}/assets/js/platformer2/GameEnv.js';

/*
* ==========================================
* ========== Game Setup ====================
* ==========================================
* Game Setup prepares the Game Levels and Objects
* 1.) There are one-to-many GameLevels in a Game
* 2.) Each GameLevel has one-to-many GameObjects
* ==========================================
*/

// Setup game data, the objects and levels
GameSetup.initLevels("{{site.baseurl}}");

/*
* ==========================================
* ========== Game Control ==================
* ==========================================
* Game Control starts the game loop and activates game objects
* 1.) GameControl cycles through GameLevels
* 2.) Each GameLevel is on a looping timer, called within the game loop
* 3.) The game loop allows the game player (user), to interact with the game objects
* 4.) A timer (or score) tracks the time of user interaction within the game
* ==========================================
*/

// Start the PRIMARY game loop
GameControl.gameLoop();

// Create an async event to start the timer when the start game button is pushed
document.getElementById('startGame').addEventListener('click', () => {
GameControl.startTimer();
});

/*
* ==========================================
* ========== Settings Control ==============
* ==========================================
* Settings Control provides the ability to select game level and change game settings
* 1.) SettingsControl must be after GameControl, it depends on GameLevels
* 2.) GameControl extends and implements LocalStorage to support the persistence of user data
* 3.) Modifications can be made to User ID, GameSpeed, Gravity, and Invert(ing) screen color
* ==========================================
*/

// Construct settings sidebar, MVC variable paradigm, and async events to trigger user interaction
SettingsControl.sidebar();

/*
* ==========================================
* ========== Event / Listeners =============
* ==========================================
* System Event listeners
* 1.) Window resize and GameEnv.resize trigger system updates
* 2.) Most event listeners remain near impacting functions
* ==========================================
*/

// Game refresh is required when the height and width of the screen are impacted
window.addEventListener('resize', GameEnv.resize);

</script>
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ plugins:
- jekyll-remote-theme
future: true
header_pages:
- 2023-11-27-CSSE-oop-game-levels.md
- 2024-01-08-CSSE-oop-game-levels2.md
- AC_csse.md
5 changes: 4 additions & 1 deletion _sass/minima/custom-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@
// @import "minima/hamilton/skins/daylight";
// @import "minima/hamilton/skins/midnight";
// @import "minima/hamilton/skins/sunrise";
// @import "minima/hamilton/skins/sunset"
// @import "minima/hamilton/skins/sunset";

// FOR PLATFORMER
@import "minima/platformer-styles.scss"
123 changes: 123 additions & 0 deletions _sass/minima/platformer-styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/// platformer-styles.scss
/// @description This stylesheet is used to style the platformer game.

/// Coding Syles in SCCS (Sass), from code below:
/// @mixin is a block of CSS declarations that can be reused in other classes, see @mixin dark-mode-color below.
/// @include is used to include a mixin in a class, see @include dark-mode-color below.
/// @extend is used to extend a class with another class, see %button below.
/// $variable is used to define a variable, see $spacing-unit, $high-emph, $dark-grey below.
/// #id is used to define an id, see #gameBegin, #gameOver, #settings below.
/// .class is used to define a class, see .sidebar below.
/// & is used to reference the parent selector, see &:hover below.
/// the double slash comments (//) are considered regular comments in Sass.
/// the triple slash comments (///) are considered documentation comments in Sass.
/// comments are not included in the compiled CSS file.
/// @import is used to import other stylesheets, see @import of this file in "_sass/minima/custom-styles.sccs".
/// see https://sass-lang.com/documentation/syntax for more information.

/// Score for the game
/// @description This ID is used to style the score for the game, key style is to ensure it is on top of other elements.
#score {
position: relative;
z-index: 2; // z-index position ensures these buttons are on top.
padding: 5px;
color: $dt-red !important; // use the high-emphasis color for the text
}

/// Game Begin, Game Over, Settings IDs
/// @description These IDs correspond to buttons in game screen. Key styling is to ensure they are on top of other elements.
#gameBegin, #gameOver, #settings, #leaderboard {
position: relative;
z-index: 2; // z-index position ensures these buttons are on top.
}

/// Color mixin
/// @description This mixin is defined to share colors with classes in this stylesheet.
@mixin dark-mode-color {
color: $high-emph !important; // use the high-emphasis color for the text
background-color: $dark-grey !important; // use the dark grey color for the background
border: 1px solid $dt-blue; // from dracula-highlight.scss
}

/// Horizontal Submenu
/// @description This class styles the horizontal submenu for score and buttons in the game. It has many style elements (e.g. placing submenu below header).
.submenu {
@include dark-mode-color; // use the dark mode color scheme
border: none; // remove setting as submenu
position: fixed;
z-index: 3; // Position on Top of other elements, as well as ID buttons above
top: $spacing-unit * 1.865; // matches minima ".site-header min-height height", reference: https://github.com/jekyll/minima/blob/master/_sass/minima/_layout.scss

// Styles for the score and buttons
#score, #gameBegin, #gameOver, #settings, #leaderboard {
display: inline-block; // Make the score and buttons inline
margin-right: $spacing-unit; // Add some margin to the right of each item
}
}

/// Sidebar class
/// @description This class styles the sidebar for settings in the game. It has many style elements (e.g. placing sidebar below header).
.sidebar {
@include dark-mode-color; // use the dark mode color scheme
border: none; // remove setting as sidebar collapse leaves residue line
position: fixed;
z-index: 3; // Position on Top of other elements, as well as ID buttons above
// left: 0; // set the sidebar to be on the left side of the page
top: 0; // calculated to be below the header and submenu
padding-top: 5px;
padding-bottom: 5px;
overflow-x: hidden; /* Disable horizontal scroll */
transition: 0.5s; /* 0.5-second transition effect to slide in the sidebar */
// following are changed by JavaScript
width: 0px;
padding-left: 0px;
padding-right: 0px;
}

/// Table class
/// @description Key style is to present game levels and make it responsive with hover highlighting.
.table.levels {
tr {
cursor: pointer; // Change the cursor to a pointer when it hovers over a row
td {
border: 1px solid $dt-blue; // from dracula-highlight.scss
}
&:hover { // Change the background when a row is hovered over
background-color: $dt-blue; // from dracula-highlight.scss

td {
background-color: inherit; // Make the background color of the td elements the same as the tr element
}
}
}
}

/// Input mixin
/// @description This mixin sets some common styles (e.g. color, height) for the input fields, avoiding duplication of common styles in each input class.
/// @param {Number} width - The width of the input field, how wide it is.
/// @param {Number} height - The height of the input field, how tall it is.
/// @param {Color} border - The border color of the input field, the outline color.
/// @param {Number} border-radius - The border radius of the input field, rounded corners.
/// @param {Number} padding - The padding inside the input field, space between the border and the text.
/// @param {String} text-align - The text alignment inside the input field, left, right, or center.
@mixin input {
@include dark-mode-color; // use the dark mode color scheme
height: 30px;
border-radius: 5px;
padding: 5px;
}

/// Input class
/// @description This class styles the userID input field, key style is to make it wider.
.input.userID {
@include input;
width: 100px; // customize width of the input field
}

/// Input class
/// @description This class styles the gameSpeed and gravity input fields, key style is to right-align the text.
.input.gameSpeed, .input.gravity {
@include input;
width: 40px; // customize width of the input field
text-align: right; // right-align input for numbers
}
54 changes: 54 additions & 0 deletions assets/js/platformer2/Background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import GameEnv from './GameEnv.js';
import GameObject from './GameObject.js';

export class Background extends GameObject {
constructor(canvas, image, data) {
super(canvas, image, data);
}

/* Update uses modulo math to cycle to start at width extent
* x is position in cycle
* speed can be used to scroll faster
* width is extent of background image
*/
update() {
this.x = (this.x - this.speed) % this.width;
}

/* To draws are used to capture primary frame and wrap around ot next frame
* x to y is primary draw
* x + width to y is wrap around draw
*/
draw() {
this.ctx.drawImage(this.image, this.x, this.y);
this.ctx.drawImage(this.image, this.x + this.width, this.y);
}

/* Background camvas is set to screen
* the ADJUST contant elements portions of image that don't wrap well
* the GameEnv.top is a getter used to set canvas under Menu
* the GameEnv.bottom is setter used to establish game bottom at offsetHeight of canvas
*/
size() {
// Update canvas size
const ADJUST = 1 // visual layer adjust; alien_planet.jpg: 1.42, try 1 for others

const canvasWidth = GameEnv.innerWidth;
const canvasHeight = canvasWidth / this.aspect_ratio;
GameEnv.backgroundHeight = canvasHeight;
const canvasLeft = 0;

this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.style.width = `${canvasWidth}px`;
this.canvas.style.height = `${GameEnv.backgroundHeight}px`;
this.canvas.style.position = 'absolute';
this.canvas.style.left = `${canvasLeft}px`;
this.canvas.style.top = `${GameEnv.top}px`;

// set bottom of game to new background height
GameEnv.setBottom();
}
}

export default Background;
22 changes: 22 additions & 0 deletions assets/js/platformer2/BackgroundHills.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import GameEnv from './GameEnv.js';
import Background from './Background.js';

export class BackgroundHills extends Background {
constructor(canvas, image, data) {
super(canvas, image, data);
}

// speed is used to background parallax behavior
update() {
this.speed = GameEnv.backgroundHillsSpeed;
super.update();
}

draw() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
super.draw();
}

}

export default BackgroundHills;
16 changes: 16 additions & 0 deletions assets/js/platformer2/BackgroundMountains.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import GameEnv from './GameEnv.js';
import Background from './Background.js';

export class BackgroundMountains extends Background {
constructor(canvas, image, data) {
super(canvas, image, data);
}

// speed is used to background parallax behavior
update() {
this.speed = GameEnv.backgroundMountainsSpeed;
super.update();
}
}

export default BackgroundMountains;
Loading

0 comments on commit a3075f9

Please sign in to comment.