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

Classic Frogger Game #594

Merged
merged 15 commits into from
Oct 5, 2022
Merged

Classic Frogger Game #594

merged 15 commits into from
Oct 5, 2022

Conversation

YuraZagor
Copy link
Contributor

@YuraZagor YuraZagor commented Sep 17, 2022

Classic Frogger Game

Demo |
Code base

The code is submitted in a dedicated feature branch.

Only code files are submitted.

Please, review.

@YuraZagor YuraZagor changed the title minimum viable product Classic Frogger Game Sep 17, 2022
@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 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. 😒

Please, make sure that your code follows the requirements

In addition to the bot's suggestions above, please post a link to the app demo in Students' chat, collect feedback and fix bugs if any based on that. When user tests are done post here a comment on that.

Universal recommendations:

  • Make sure your code follows General Requirements
  • Use common sense or seek for an advice whenever requirements look ambiguous or unclear.

By the way, you may proceed to the next task before this one is reviewed and merged.

Sincerely yours,
Submissions Kottachecker 😺

@YuraZagor
Copy link
Contributor Author

self-check done

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.

@YuraZagor good start. Needs improvements and double-check against requirements.

@@ -0,0 +1,92 @@
const allEnemies = [];
const allSpeeds = [200, 250, 350];
const rangeY = [73, 156, 239];
Copy link
Member

Choose a reason for hiding this comment

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

What are these magic numbers?
As a peer developer I am tasked to add another Y. How do I calculate it? Ideally I want to add a row number and let computer do what they were invented to do - calculations.
Also true for other numbers representing pixels across the entire codebase.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 40 to 41
player.x = playerStartX;
player.y = playerStartY;
Copy link
Member

Choose a reason for hiding this comment

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

Item 4.iii of the requirements

)
};

player.handleInput = function (direction) {
Copy link
Member

Choose a reason for hiding this comment

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

One of the purposes of OOP is that class defines all behaviors of the class.
Please explain why this approach was taken.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My logic then was as follows: this kind of behavior is typical only to player object. As in this case we do not need this functionality in Player-prototyped enemy-objects , so I did not prototype it in Player.
Also, TBH, I am a newbie who tryed ways - and this one worked. Re-wrote with Player.prototype

Copy link
Member

Choose a reason for hiding this comment

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

this kind of behavior is typical only to player object
That's correct. Also true is that any method on Player prototype is typical to player object.

player.propertyName = function () worked, as expected. We still can have functions as object properties.

But what if we have a multiplayer game? OOP helps to have objects blue-prints and avoid code duplication.

Oh, I see. You based enemies on Player.
So in fact Player is an "any" character.

The good thing was that you came up with having a base class for shared properties and behaviour.
The improvemnt would be to have both Enemy and Player class extend such base class with their own specifics.
Are you up to improve your code accordingly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, that way it makes more sense and now I was able to solve ' player.x = playerStartX' omitting .

Done

@OleksiyRudenko OleksiyRudenko added the OQ Open Question from reviewer requiring explanation label Sep 26, 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.

@YuraZagor a bit of wrong direction taken.
Check the difference between class and class instance.
Requirements provide a hint on how to resolve the issue.
Take a step back and try again.

Comment on lines 49 to 53
if (this.y === Player.y){
if ((this.x - Player.x < collisionOffset ) && (Player.x - this.x < collisionOffset )) {
Player.x = playerStartX;
Player.y = playerStartY;
};
Copy link
Member

Choose a reason for hiding this comment

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

Before we had here a reference to an instance of Player class stored in a global variable.
Now we directly refer here to the class itself.
Check the difference between class and an instance of a class.
Class is a blue-print. Enemies are intended to interact with specific instance (or instances in multiplayer mode) of Player class.
Also demo doesn't seem to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure that I fully understand it all, but as I get it I should pass the instance as an attribute, so that if we change the passed object we can still use the same method. Hope that was it

Copy link
Member

Choose a reason for hiding this comment

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

...pass the instance as an attribute...
As an argument. Just for the sake of correct use of terminology

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.

@YuraZagor nearly there

Comment on lines 10 to 17
const spriteRepositioningY = -10
const playerStartX = 2*cellX;
const playerStartY = 5*cellY + spriteRepositioningY ;
const fieldWidth = 5*cellX;
const fieldHight = 5*cellY;
const row1 = cellY + spriteRepositioningY
const row2 = 2*cellY + spriteRepositioningY
const row3 = 3*cellY + spriteRepositioningY
Copy link
Member

Choose a reason for hiding this comment

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

Why mixed style of semicolons usage?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad
Actually, I didn't have the habbit to use those before the course, and now I try to get used to them but at times I forget in haste

Comment on lines 15 to 18
const row1 = cellY + spriteRepositioningY
const row2 = 2*cellY + spriteRepositioningY
const row3 = 3*cellY + spriteRepositioningY
const rangesY = [row1, row2, row3];
Copy link
Member

Choose a reason for hiding this comment

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

How about const rangesY = [1, 2, 3].map(some maths here)?
Whenever you are tempted to write var1, var2, var3 it is a clear sign that you need to create an array with some maths.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is really great and concise, never thought that way. Done

this.x = enemyRestartX;
this.speedX = allSpeeds[Math.floor(Math.random()*3)];
};
this.checkColision(player)
Copy link
Member

Choose a reason for hiding this comment

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

checkCollision doesn't refer to global variable player, but now update does.
So the problem remains.
Feel free to ask specific questions to the hint from the requirement.
Yet another hint: there is a reason that you pass sprite by reference and do not refer to it directly.

Copy link
Contributor Author

@YuraZagor YuraZagor Oct 3, 2022

Choose a reason for hiding this comment

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

I guess I finally got the point.
Though it is not clear how it works, will have to work on that - I mean as I see it passing instance as arg works even when player hasn't been created yet in the code

@YuraZagor
Copy link
Contributor Author

self-check done
UAT done

@OleksiyRudenko OleksiyRudenko added UAT-done Student confirmed User Acceptance Tests are done and collected feedback is processed self-check-done Student confirmed that self-checks against requirements/common-mistakes are done labels Oct 5, 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.

@YuraZagor great job done!

Comment on lines +52 to +56
function addBug() {
rangesY.forEach ( (levelMark)=> allEnemies
.push( new Enemy(0, levelMark, allSpeeds[Math.floor(Math.random()*3)], player))
)
};
Copy link
Member

Choose a reason for hiding this comment

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

This wasn't a part of the requirements. But try to scale that narrow requirement onto a bigger scale.
A well designed function relies only on parameters it receives and doesn't refer to any global variables.
This way it encapsulates business logic it designated to implement.
In big codebases following this principle will pay.

@OleksiyRudenko OleksiyRudenko merged commit ac6b2a3 into kottans:main Oct 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OQ Open Question from reviewer requiring explanation self-check-done Student confirmed that self-checks against requirements/common-mistakes are done Stage0.1 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.

3 participants