Skip to content
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 by Ivan Chukhalo (the task is a part of #9 'Object Oriented JS' module) #347

Merged
merged 7 commits into from
Oct 13, 2022

Conversation

ivan-chukhalo
Copy link
Contributor

@ivan-chukhalo ivan-chukhalo commented Aug 29, 2022

Frogger game

Demo |
Code base

The code is submitted in a dedicated feature branch.

Only code files are submitted.

Please, review.

@github-actions
Copy link

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 list

Relates to Object-Oriented JavaScript task.

Check-list - definition of done

  • employ ES6 features like const, let etc. (with exclusion of ES6 class syntax)

  • the code is very DRY

  • Requirements re Constants:

    • all numbers like block dimensions, initial locations are defined as named constants (e.g. const STEP = 101;) as otherwise numbers scattered across code base look cryptic; named constants add semantic meaning and improve readability
    • every number that has a semantic purpose (like those listed above) should be defined as constants; think of how your code reads - the closer to plain English the better
    • there are core constants and derived constants
      (e.g. derived constant const FIELD_WIDTH = BLOCK_WIDTH * BLOCKS_NUMBER;)
    • arrays of constants are also constants
      (e.g. const INITIAL_POSITIONS = [1,2,3,4].map(rowNumber => rowNumber * BLOCK_HEIGHT);)
    • const objects help organizing and structure const data even better
      (e.g. const PLAYER_CONF = { initialPosition: {x: 1, y: 5}, sprite: '...', ...etc... };
  • Requirements re OOP:

    • OO is implemented using JS prototype chain object model (not ES6 classes syntax)
    • classes do not refer to any global variables, like global variable player, which is an instance of Player class
      (referring to global constants and globals provided by the gaming platform like Resources is OK);
      Hint: pass Player instance as an argument to every enemy
    • Separation of Concerns principle is followed
      (e.g. update method does only rendering and doesn't contain any unrelated inline code; for example collision check is defined as a dedicated method and only called from inside update)
    • Nice To Have: properties common for some classes are generalized into a base class
      (e.g. there is Character base class, which is extended by Enemy and Player classes)
    • class extension is implemented using Subclass.prototype = Object.create(Superclass.prototype), not Subclass.prototype = new Superclass(params);; Helpful resource
  • Most common mistakes

    • Make sure target = condition ? valueWhenConditionTrue : valueWhenConditionFalse is used instead of condition ? target = valueWhenConditionTrue : target = valueWhenConditionFalse; Conditional (ternary) operator

Universal recommendations:

  • Give variables and functions meaningful names. Avoid generic names like item, element, key, object, array or their variations. Exception: helper functions that are specifically and intentionally designed to be multipurpose.
  • Function names should start with a verb as they denote actions; variables are normally nouns; boolean variables/functions start with is, does, has etc; variable containing multiple entities and functions returning lists contain entity name in plural form.
  • Have consistent code style and formatting. Employ Prettier to do all dirty work for you.
  • Use common sense or seek for an advice whenever requirements look ambiguous or unclear.

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,
Submissions Kottachecker 😺

@ivan-chukhalo
Copy link
Contributor Author

ivan-chukhalo commented Sep 1, 2022

@OleksiyRudenko

I've run through the check-list, made few changes in my work. Seems it does not have common mistakes anymore.
Please, review.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivan-chukhalo great job!

Comment on lines 1 to 8
const AVAILABLE_ROWS_FOR_ENEMIES = [63, 146, 229];
const allEnemies = [];

const WIDTH_OF_GAME_SPRITES = 100;
const COLUMNS_ON_GAME_FIELD = 5;
const HEIGH_OF_GAME_FIELD_CELL = 83;
const PLAYER_BUG_CENTERS_DISTANCE_OF_TOUCHING = 80;
const Y_OF_GAME_FIELD_ROWS = [63, 146, 229, 312, 395];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There must be some formula to calculate pixel Y from row number...
Good news is that computers are made to do calculations for us. We need to benefit from this fact to make our lives better.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivan-chukhalo an improtant fix to do.

};

Enemy.prototype.doesHitPlayer = function (){
if (Math.abs(this.x - player.x) <= PLAYER_BUG_CENTERS_DISTANCE_OF_TOUCHING && this.y === player.y){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* [ ] classes do not refer to any global variables, like global variable `player`, which is an instance of `Player` class
  (referring to global constants and globals provided by the gaming platform like `Resources` is OK);
  Hint: pass `Player` instance as an argument to every enemy

…OF_GAME_FIELD_ROWS) and rewrite Enemy.prototype.doesHitPlayer() functions so it uses input parameter from now
@ivan-chukhalo
Copy link
Contributor Author

Thank you for comments. I've made requested changes.

Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivan-chukhalo nearly there


Enemy.prototype.update = function(dt) {
this.x = this.x >= this.xAxisMax ? this.x = this.xInitial : this.x + dt * this.speedKoef;
this.doesHitPlayer(player);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

player is still a global variable.
The requirements provide a hint on how to resolve the problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OleksiyRudenko, excuse me.

It seems like I've missed this row or I got rid of global variables dependencies in the project, then made some extra changes in the code and added new dependency without noticing it)

Fixed issue. Review, please.

Copy link
Member

@OleksiyRudenko OleksiyRudenko Oct 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line of code seems to remain unchanged. player is a global variable.
The requirements provide hint on how to resolve the issue.

@ivan-chukhalo
Copy link
Contributor Author

@OleksiyRudenko

User Acceptance Tests have been conducted and no bugs have been found.

@OleksiyRudenko OleksiyRudenko added the UAT-done Student confirmed User Acceptance Tests are done and collected feedback is processed label Oct 9, 2022
@OleksiyRudenko
Copy link
Member

Note that UAT doesn't make issues pointed out by a mentor obsolete.

…ions into the class, change name of Enemy.doesHitPlayer() parameter, fix Enemy.doesHitPlayer() so it doesn't depend on Player class
@ivan-chukhalo
Copy link
Contributor Author

@OleksiyRudenko

Added an income parameter (refered to another class entity) for a class' function and forgot to rewrite function's body in previous commit😱😩. Excuse me.

I fixed the problem (as I consider), ran through code and made few extra changes to fix things which I thought could be mistakes. Basically, I did an extra self check.

@OleksiyRudenko OleksiyRudenko added the self-check-done Student confirmed that self-checks against requirements/common-mistakes are done label Oct 10, 2022
Copy link
Member

@OleksiyRudenko OleksiyRudenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ivan-chukhalo great job!


let player = new Player();
for (let elem of AVAILABLE_ROWS_FOR_ENEMIES.concat(AVAILABLE_ROWS_FOR_ENEMIES)){
allEnemies.push(new Enemy(elem, player));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elem is a bad naming

@OleksiyRudenko OleksiyRudenko merged commit 80d4e95 into kottans:main Oct 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
self-check-done Student confirmed that self-checks against requirements/common-mistakes are done task-Frogger UAT-done Student confirmed User Acceptance Tests are done and collected feedback is processed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants