meth-meth-method / super-mario Goto Github PK
View Code? Open in Web Editor NEWCreate a Super Mario game in vanilla JS from scratch.
Home Page: http://bit.ly/2i7u5ks
Create a Super Mario game in vanilla JS from scratch.
Home Page: http://bit.ly/2i7u5ks
In castle levels, bowsers fire can appear in the level without being near bowser.
I'm curious why you chose to define level.background.ranges
as arrays rather than objects with x1
, x2
, y1
, and y2
properties?
I do like the use of destructuring into named variables in:
background.ranges.forEach(([x1, x2, y1, y2]) => { // ...
... but you could still use object destructuring, with the object's properties:
background.ranges.forEach(({ x1, x2, y1, y2 }) => { // ...
Enjoyed the video. Thanks!
When jumped on the axe and Bowser dies, Mario should animate down into the room behind Bowser, print text on the screen and progress to the next level.
Dependant on #98
We need 4 types of moving platforms.
1, one that goes on a track in one direction, as seen in level 1-2.
2, one that goes up and down in a pendulum move, as seen in level 1-3.
3, one that is suspended from ropes and move the other platform, and breaks loose both platforms when maxum bottom is reached, as seen in level 4-3.
4, one that goes from side to side as seen in castle
I had a problem with the timing on Firefox. It was driving me crazy : "Why it's working perfectly fine on chrome, but not in FF ??". In chrome the jump was smooth, but in FF it's was like Mario started near the end of the jump.
Firefox doesn't start as quickly as Chrome, so each time a launched the timer, mario was already near the end when it rendered the canvas.
First start - time : 746 (FF), 117 (Chrome), so i came up with :
it needed to render 42 Frames for Firefox vs 7 Frames for chrome.
this.updateProxy = (time) => {
if (lastTime != 0) {
accumulatedTime += (time - lastTime) / 1000;
while(accumulatedTime > deltaTime) {
this.update(deltaTime);
accumulatedTime -= deltaTime;
}
}
lastTime = time;
this.enqueue();
}
use the pixels of a .png image to build the design of the levels. for example a red pixel for a brick and a blue pixel for a turtle. With image analysis rather than level json
Koopa paratroopa needs a trait that makes him fly.
He will fly up and down within a given min and max on the Y axis.
Fake Bowser sits in the end of each *-4 level.
He jumps, open his mouth and spits fire.
64x64 sprite.
Can be killed with 5 fireballs, revealing its true enemy upon death or by stomping the axe, removing the bridge and falls down into lava.
1-4: Little Goomba - fire
2-4: Green Koopa Troopa - fire
3-4: Buzzy Beetle - fire
4-4: Spiny - fire
5-4: Lakitu - fire
6-4: Bloober - fire + hammer
7-4: Hammer Brother - fire + hammer
Video of all bowsers: https://www.youtube.com/watch?v=2Wr4G1_L1mM
super-mario/public/js/traits/Go.js
Line 12 in 3ee49f8
If speed is defined in pixels per seconds, there is no need to multiply it by deltaTime
to set velocity of entity.
And if you are pressing key, you want Mario move with constant velocity.
Use Web Audio API in favor for basic playback embedding with HTML5 Audio element.
The Web Audio API offers more capabilites than the HTML5 Audio element and in our use case it is critical to create seamless looping of super mario music.
Jake Archibald did a write up on the subject in 2016: https://jakearchibald.com/2016/sounds-fun/
Looping: https://webaudio.github.io/web-audio-api/#looping-AudioBufferSourceNode
super-mario/public/js/TileCollider.js
Line 30 in dc5ab34
also in lines 37, 67 and 74:
You change the bounding box in a collision check. This can't be right.
I solved this error in my typescript Version at https://just-run.it/#/rySrbk86W/7 on File TileCollider.ts
Greetings, Andreas
Red Koopa needs a trait, perhaps a flag to pendulumwalk, that prevents him from fall down from blocks.
super-mario/public/js/entities/Goomba.js
Line 25 in dc5ab34
If you kill goomba by stomping on it you bounce of. Thats the right behavior.
But until the goomba leaves the level (the 2 seconds the flat animation is active) you bounce over and over again - and thats not right.
If you add
us.canCollide = false
to this position it won't happen anymore the dead goomba falls right through the level.
So you have to split up the canCollide property on the Entity class to
You have to Update the Level update function:
public update(deltaTime: number) {
this.entities.forEach(entity => {
entity.update(deltaTime, this);
entity.position.x += entity.velocity.x * deltaTime;
if (entity.canCollideWithBackground) {
this.tileCollider.checkX(entity);
}
entity.position.y += entity.velocity.y * deltaTime;
if (entity.canCollideWithBackground) {
this.tileCollider.checkY(entity);
}
entity.velocity.y += this.gravity * deltaTime;
});
this.entities.forEach(entity => {
if (entity.canCollideWithOtherEntity) {
this.entityCollider.check(entity);
}
});
this.totalTime += deltaTime;
}
You have to update the EntityCollider check function:
public check(subject: Entity) {
this.entities.forEach(candidate => {
if (subject === candidate || !candidate.canCollideWithOtherEntity) {
return;
}
if (subject.boundingBox.overlaps(candidate.boundingBox)) {
subject.collides(candidate);
candidate.collides(subject);
}
})
}
Line 36 in 0baa7d4
Hello,
The purpose of the timer is to decouple the physics from the frame rate. If the frame rate drops, Mario's jumping arc should still stay the same.
The code as its written certainly does that, but I think it is causing many unnecessary repaints.
If the frame rate drops to 1 frame a second it'll still force 60 repaints, even though all but the 60th one will not be see on the screen.
I think you should have an extension to the Timer, maybe:
const timer = new Timer(1/60)
timer.update = (deltaTime, visible) => {
//physics update logic goes here
if (visible) {
comp.draw(context)
}
}
timer.start()
I love this Youtube Channel. Also, the Megaman graphics at the beginning makes me hope that one day you'll do one of those later. :)
Cheers
super-mario/public/js/traits/Killable.js
Line 15 in 85e56ea
Minor bug:
If you encueue
this.dead = true;
in the kill method you should encueue also all changes in revive:
revive = () => {
this.enqueue(() => {
this.dead = false;
this.deadTime = 0;
});
};
The kicked koopa shell should be deadly for both enemies and mario.
Kicking the shell should play /audio/fx/kick.ogg
The shell should play /audio/fx/brick-bump.ogg
when colliding with tiles.
Mario should be able to grow to large mario when collecting a mushroom.
Sprite definitions ready, animation to be done.
Should play /audio/fx/power-up-consume.ogg
When Mario is large, he should be able to shrink when in contact with enemies and deadly things.
He should use shrink animation (yet to be done), and also be invincible for x amount of time, indicated by "transparency" simulated by omitting every 2nd frame.
He should play /audio/fx/pipe.ogg
when shrinking. (perhaps rename this sound into something more general.
While testing this on my laptop it appears that runlevel is called multiple times. I have been trying to debug this issue myself for a while but I still have not figured out why it is happening.
This is on a fresh clone of the master branch.
Here is a demo of the issue. https://imgur.com/dlZVpEU
Mario should be able to end the level by riding the flag pole and collect points depending on where on the flag he touches, and then autowalk #61 to the castle.
If you allow me to jump in and implement ESlint and style-guide based on "standard", I could fork your project and make a PR for you.
I'm enjoying your channel) You do amazing job. Waiting each new episode. Thank you!
Would love to participate)
As I see, you are using Sublime text editor for super-mario development.
I used it for many years, but now switched to Atom. It has better plugins and development experience, and evolving much faster than Sublime.
super-mario/public/js/traits/Killable.js
Line 24 in dc5ab34
You delete an entity in the collection of all entities in the level while you are looping over all entities in the level.
This causes a undefined behavior within the loop.
You should mark the entity for removing and remove it after the loop.
Hi, I really love the series so far.
Just a quick question, will you reorganize "main.js"?
Also, should Mario's initial position be in the JSON file for the levels.
I love everything you're doing! It is very interesting to see the code evolve from episode to episode and to look back at previous episodes and see the changes.
Great project.
I noticed that You are using absolute paths in certain places and relative in others. I think it should be relative everywhere.
This is a list of absolute paths in files:
index.html line 18
js/loaders.js line 20
js/loaders/level.js line 37
sprites/goomba.json line 2
sprites/koopa.json line 2
sprites/mario.json line 2
sprites/overworld.json line 2
sprites/underworld.json line 2
Good luck in the project.
Koopa paratroopa needs to jump and become a regular koopa when stomped.
Change aspect ratio of canvas and context to 4:3, 320x240
instead of NES defaults of 256x240.
Create fish entity "cheep cheep".
Unaffected by ground or corals.
4 different types:
Issue partly resolved with #122
on entity collider we have both subject.collides(candidate)
and candidate.collides(subject)
and entity nested loops cause every subject != candidate
pair go to this.
As result, on collision, for example mario.collides(goomba)
is called with subject === mario
and candidate == goomba
and then with subject === goomba
and candidate === mario
.
With such a loop nesting calling only subject.collides(candidate)
is enough.
Red koopa is the same as green koopa but with an added trait that don't permits him to fall down from a tile.
This issue is dependant on #55
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.