-
-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Frogger Game #287
Frogger Game #287
Conversation
Hey! Congratulations on your PR! 😎😎😎 Let's do some self-checks to fix most common issues and to make some improvements to the code before reviewers put their hands on the code. Go through the requirements/most common mistakes listed/linked below and fix the code as appropriate. If you have any questions to requirements/common mistakes feel free asking them here or in Students' chat. When you genuinely believe you are done put a comment stating that you have completed self-checks and fixed code accordingly. Also, be aware, that if you would silently ignore this recommendation, a mentor can think that you are still working on fixes. And your PR will not be reviewed. 😒 Frogger Arcade Game -- JS OO exercise check listRelates to Object-Oriented JavaScript task. Check-list - definition of done
Universal recommendations:
Also take a note of the requirements above and follow them in all your future projects. By the way, you may proceed to the next task before this one is reviewed and merged. Sincerely yours, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crealime pretty well done!
At times calculations look overcomplicated. Probably, operating with concepts of row and column (truly questionable as enemies do not jump across the columns) would make it simpler.
Pixels make sense only at image drawing phase and characters intersections.
Player and enemy collide when they are on the same row and player's x
is within specific range based on enemy's x
. Collision with gems can be done based solely on row/column match.
This code works. But as a peer developer I feel I gonna struggle with understanding and deducing a lot of maths involved.
Can we simplify it a bit?
// all computers. | ||
this.x += this.speed * dt | ||
|
||
if (this.x > 530) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this mysterious number - 530
? As a peer developer I want to read and understand the code in order ro be able to contribute effectively.
This refers to this number and other numbers across the code that are not defined as constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to WIDTH_CANVAS.
if (player.level === 1) { | ||
setStars('images/Gem Blue.png') | ||
} | ||
else if (player.level === 2) { | ||
setStars('images/Gem Green.png') | ||
} | ||
else if (player.level === 3) { | ||
setStars('images/Gem Orange.png') | ||
} | ||
else { | ||
setStars('images/Gem Red.png') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider dictionary pattern here (use appropriate domain-specific naming).
const valuesDictionary = {
1: 'a',
2: 'b',
3: 'c',
4: 'd',
}
const defaultValueKey = 4
valuesDictionary[2] || valuesDictionary[defaultValueKey]
valuesDictionary[999] || valuesDictionary[defaultValueKey]
You most likely may also re-use the dictionary in the other fragments of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! This is a good idea. Done.
if (player.level === 1) { | ||
player.level = 2 | ||
allEnemies = creteEnemies(allEnemies.length + 1) | ||
setStars('images/Gem Green.png') | ||
} | ||
else if (player.level === 2) { | ||
player.level = 3 | ||
allEnemies = creteEnemies(allEnemies.length + 1) | ||
setStars('images/Gem Orange.png') | ||
} | ||
else if (player.level === 3) { | ||
player.level = 4 | ||
allEnemies = creteEnemies(allEnemies.length + 1) | ||
setStars('images/Gem Red.png') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a peer developer I am tasked to add 5 more player levels.
Can we please have next state calculable based on current player level? I see the repetition pattern here.
See also comment on dictionary pattern below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
function creteEnemies(num) { | ||
if (num > 6) num = 6 | ||
const arrEnemies = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enemies
part already says the variable contains many similar instances. Referring of data type is redundant and abbreviation (arr
) makes it obscure anyway. There is a reason we do not write numY
, numSpeed
, strMessage
, arrAllEnemies
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand. Fixed. And I change the functions creteEnemies and createStars so that they change the arrays allEnemies and allStars directly.
for (let i = START_ENEMIES_Y_POSITION; i < num * Y_STEP; i += Y_STEP) { | ||
let y = i | ||
if (i > START_ENEMIES_Y_POSITION + Y_STEP * 2 && i <= START_ENEMIES_Y_POSITION + Y_STEP * 3) | ||
y = INITIAL_ENEMIES_Y_POSITIONS[0] | ||
else if (i > START_ENEMIES_Y_POSITION + Y_STEP * 3 && i <= START_ENEMIES_Y_POSITION + Y_STEP * 4) | ||
y = INITIAL_ENEMIES_Y_POSITIONS[1] | ||
else if (i > START_ENEMIES_Y_POSITION + Y_STEP * 4 && i <= START_ENEMIES_Y_POSITION + Y_STEP * 5) | ||
y = INITIAL_ENEMIES_Y_POSITIONS[2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we calculate pixel y
positions based on something more comprehensible, e.g. playfield row number? Add row offset, multiply by row height?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Also please before submitting your next task make your code editor do indents with 2 spaces, not tabs. |
Thanks a lot for your review! Сode got really better. I think I redid everything you suggested. If I misunderstood something, please write to me. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crealime great job!
Check the comments below and take these as a source of learning and inspiration.
let y = i | ||
if (i === 4) y = 1 | ||
if (i === 5) y = 2 | ||
if (i === 6) y = 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use maths more often whenever there is any correlation.
const START_PLAYER_X_POSITION = X_SIZE * START_COLUMN | ||
const START_PLAYER_Y_POSITION = Y_SIZE * START_ROW - Y_OFFSET_PLAYER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to group constants per their common features.
e.g.
const FIELD = {
rows: 5,
cols: 6,
}
const FIELD_PIXEL_BASED_PROPS = {
width: 530,
height: 999,
}
const FIELD = {
PIXEL_BASED: {
TILE: {
width: 50,
height: 110,
}
},
ROW: {
count: 7,
start: 5,
},
COL: {
count: 8,
start: WHATEVER * 5,
},
}
const FIELD.PIXEL_BASED.DIMENSIONS = {
width: FIELD.PIXEL_BASED.TILE.width * FIELD.COL.count,
height: // .similar calcs
};
Look, how reads full path FIELD.PIXEL_BASED.width
. Practically, you replace some underscores with dots, yet the constants definition has some logical structure.
The above is a quick example (so naming is not well elaborated) to give you some ideas and illustrate how we can leverage nested data to put data into some logical structure yet keeping things readable.
Also it might be more reasonable to have essential numbers in a constant object different from a constant object that contains calculated constants.
The best frogger I've ever seen! |
Frogger Game
Demo |
Code base
The code is submitted in a dedicated feature branch.
Only code files are submitted.
Please, review.