From ea434635a0216d8a0e022ae8c6b11702ff24f9d1 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Thu, 7 May 2020 23:38:01 -0400 Subject: [PATCH 01/11] Adds an outline for new tutorial. --- docs/tutorials/virtual-tennis/index.rst | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docs/tutorials/virtual-tennis/index.rst diff --git a/docs/tutorials/virtual-tennis/index.rst b/docs/tutorials/virtual-tennis/index.rst new file mode 100644 index 00000000..ae46d5c3 --- /dev/null +++ b/docs/tutorials/virtual-tennis/index.rst @@ -0,0 +1,29 @@ +=============================== +Virtual Tennis +=============================== + +In this tutorial, we're going to build a game like Pong ---link---. + +Before we start, let's think through what components make up a game like pong: + +1. A ball that bounces on the walls +2. player paddles that can deflect the ball +3. A scoreboard that tracks how many times the ball leaves play. +4. A way to play more than one game. + +This sounds like a small bit, but we're going to break these down into even +smaller steps and test as we go. + +1. A window +1. A ball that bounces on the edges of the screen. +2. A player paddle that can be moved. +3. Collision between player paddle and ball. +4. A score board tracking how many times the player hits the far side of the + screen. +5. Removing the ball from play when it hits the far wall. +6. Launching the ball with a key press. +7. Removing the ball if it hits the player's wall. +8. Adding a second player paddle. +9. Adding a new score board for second player. +10. End the game. +11. Ideas for making the game your own. \ No newline at end of file From 14951ab7394259df183b1acf36a390228ef1da5e Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Fri, 15 May 2020 22:48:06 -0400 Subject: [PATCH 02/11] Adds preamble and setup instruction to virtual-tennis tutorial. --- docs/conf.py | 1 + docs/tutorials/index.rst | 4 + docs/tutorials/virtual-tennis/index.rst | 87 +++++++++++++++++----- docs/tutorials/virtual-tennis/setup.rst | 94 ++++++++++++++++++++++++ docs/tutorials/virtual-tennis/window.rst | 4 + requirements-docs.txt | 1 + 6 files changed, 172 insertions(+), 19 deletions(-) create mode 100644 docs/tutorials/virtual-tennis/setup.rst create mode 100644 docs/tutorials/virtual-tennis/window.rst diff --git a/docs/conf.py b/docs/conf.py index ffe1ed84..e6cf435a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -43,6 +43,7 @@ 'sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx', + 'sphinx_tabs.tabs', ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst index f92452a1..8a1b4a72 100644 --- a/docs/tutorials/index.rst +++ b/docs/tutorials/index.rst @@ -5,3 +5,7 @@ Tutorials live here, except for the basic Quick Start tutorial. A tutorial is an complete project that takes you from an empty file to a working game. + + +.. toctree:: + virtual-tennis/index \ No newline at end of file diff --git a/docs/tutorials/virtual-tennis/index.rst b/docs/tutorials/virtual-tennis/index.rst index ae46d5c3..5487a4b0 100644 --- a/docs/tutorials/virtual-tennis/index.rst +++ b/docs/tutorials/virtual-tennis/index.rst @@ -2,28 +2,77 @@ Virtual Tennis =============================== -In this tutorial, we're going to build a game like Pong ---link---. +.. toctree:: + :hidden: + :maxdepth: 0 + :titlesonly: -Before we start, let's think through what components make up a game like pong: + setup + window -1. A ball that bounces on the walls -2. player paddles that can deflect the ball -3. A scoreboard that tracks how many times the ball leaves play. -4. A way to play more than one game. +In this tutorial, we're going to build a game virtual tennis game in the vein +of Pong_. We're going to go through the whole process: planning our approach, +breaking out individual tasks, setting up our environment, and coding. -This sounds like a small bit, but we're going to break these down into even -smaller steps and test as we go. +Before you start writing code on a project, it's best to think about the game +we're trying to make. For research, go try this implementation of +`Pong `_ on the internet +archive. + +Let's think about what's going on in this version: + +#. It opens on a menu with sample play happening in the background. +#. The menu explains all the controls. +#. When you start a one player game, you receive control of one of the paddles. +#. The ball launches, and you need to move up and down to deflect the ball. +#. The ball bounces off the top and bottom walls. +#. If either of you miss the ball, the other player's score goes up. +#. If a player reaches 15 points, the game ends with fanfare and the word + "Winner!" printed repeatedly on that side of the screen. +#. Then it goes back to the menu. + +Now that we've looked at an example of our project, let's identify the +important parts: + +* The core game play is a ball and two paddles, each controllable by a player. +* The ball needs to be able to bounce off the top and bottom wall and either + paddle. +* The paddles need to be able to move. +* We need to be able to track the score. +* We need to be able to end the game. + +This tutorial will break each of these requirements into smaller pieces so we +can test features as we go. + +Before we get started, you'll need a few things done first: + +#. Install python 3.8 on your system. We suggest installing from python.org for + best results. For more information, see the + `Django Girls tutorial `_. + for more specific instructions on installation. +#. Install a code editor. We suggest PyCharm, Sublime Text, GEdit or VSCode. + Extra information and suggestions can be found at + `Django Girls `_. +#. You'll also need to know the basics of Python. Again, Django Girls has a + great `tutorial `_ + for this. + +Once you have those things done, you can move on to our first step: setting up +our project. + + +( The following will be deleted before final publication.) 1. A window -1. A ball that bounces on the edges of the screen. -2. A player paddle that can be moved. -3. Collision between player paddle and ball. -4. A score board tracking how many times the player hits the far side of the +2. A ball that bounces on the edges of the screen. +3. A player paddle that can be moved. +4. Collision between player paddle and ball. +5. A score board tracking how many times the player hits the far side of the screen. -5. Removing the ball from play when it hits the far wall. -6. Launching the ball with a key press. -7. Removing the ball if it hits the player's wall. -8. Adding a second player paddle. -9. Adding a new score board for second player. -10. End the game. -11. Ideas for making the game your own. \ No newline at end of file +6. Removing the ball from play when it hits the far wall. +7. Launching the ball with a key press. +8. Removing the ball if it hits the player's wall. +9. Adding a second player paddle. +10. Adding a new score board for second player. +11. End the game. +12. Ideas for making the game your own. diff --git a/docs/tutorials/virtual-tennis/setup.rst b/docs/tutorials/virtual-tennis/setup.rst new file mode 100644 index 00000000..136e06e5 --- /dev/null +++ b/docs/tutorials/virtual-tennis/setup.rst @@ -0,0 +1,94 @@ +=============================== +Setup +=============================== + +For this project, we're going to want to have a project folder and a virtual +environment set up. Follow along and we'll get that set up. + +.. note:: Before continuing, if you're new to software development, you + should pick a directory or folder on your computer to save your project. A + common name for this directory is ``src``. It can live anywhere you like. You + should copy the path from your file explorer and hold on to it, we're going + to use it later. We reference this path as ``/path/to/src/``. + +So the first thing you need to do is open your terminal. + +.. tabs:: + + .. group-tab:: Windows + + On Windows, there are two terminals: cmd and powershell. If you're not + sure which to pick, choose cmd. Future directions are written with this + terminal in mind. + + .. group-tab:: MacOS + + The MacOS default terminal is just called Terminal. + + .. group-tab:: Ubuntu + + (fill out later) + +With your terminal open, you're going to want to navigate to the +``/path/to/src/``. After that, we'll set up a project directory, and then +navigate into it. In the commands below, replace ``/path/to/src/`` with your +specific path you saved earlier. The name ``virtual-tennis`` is a nice +descriptive name for your project folder, but you can change the name if you'd +like. + +.. warning:: Each of these steps has multiple commands. Make sure to enter them + one at a time and hit the enter or return key and wait until they stop + putting new text on the screen before the next command. + +On all systems: :: + + cd /path/to/src/ + mkdir virtual-tennis + cd virtual-tennis + +Our next step is to set up a virtual environment. We're going to use the python +library ``venv`` for this. After creating it, we need to activate it, and +install ``ppb``. Below, we call our virtual environment ``.venv``, but this is +only one of many possible names. If you change the name, replace it in following +commands with your new name. The structure in a virtual environment doesn't +change based on its name. + +.. note:: A virtual environment is a way to isolate the requirements of your + project from other Python projects on your computer. This lets you have + projects with conflicting requirements, like two different versions of + ``ppb``. + +.. tabs:: + + .. group-tab:: Windows + + :: + + py -3.8 -m venv .venv + .venv\Scripts\activate + python -m pip install ppb + + .. group-tab:: MacOS + + :: + + python3.8 -m venv .venv + source .venv/bin/activate + python -m pip install ppb + + .. group-tab:: Ubuntu + + (add later) + +The last step will depend on the code editor you've picked. If you're using an +IDE (PyCharm, VSCode, or similar) you'll want to open your project in your IDE. + +If you're using a plain text editor (GEdit, Notepad++) open it, but don't create +any files yet. + +Keep your terminal open, you're going to use it later. If you close it, you +should navigate back to your project folder and activate the virtual environment +again. + +With all of this out of the way, we can move on to our first step: Creating a +window. diff --git a/docs/tutorials/virtual-tennis/window.rst b/docs/tutorials/virtual-tennis/window.rst new file mode 100644 index 00000000..5176dd2f --- /dev/null +++ b/docs/tutorials/virtual-tennis/window.rst @@ -0,0 +1,4 @@ +=============================== +Opening a Window +=============================== + diff --git a/requirements-docs.txt b/requirements-docs.txt index 82133027..99017e4a 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,2 +1,3 @@ sphinx sphinx_rtd_theme +sphinx-tabs \ No newline at end of file From 111fa5588eaf604a20a993f6bc83c723358a28f5 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Sat, 16 May 2020 15:02:48 -0400 Subject: [PATCH 03/11] Adds instructions for opening and manipulating the window. --- docs/tutorials/virtual-tennis/setup.rst | 8 ++- docs/tutorials/virtual-tennis/window.rst | 82 ++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/virtual-tennis/setup.rst b/docs/tutorials/virtual-tennis/setup.rst index 136e06e5..6d3df74a 100644 --- a/docs/tutorials/virtual-tennis/setup.rst +++ b/docs/tutorials/virtual-tennis/setup.rst @@ -40,7 +40,9 @@ like. one at a time and hit the enter or return key and wait until they stop putting new text on the screen before the next command. -On all systems: :: +On all systems: + +.. code-block:: cd /path/to/src/ mkdir virtual-tennis @@ -62,7 +64,7 @@ change based on its name. .. group-tab:: Windows - :: + .. code-block:: py -3.8 -m venv .venv .venv\Scripts\activate @@ -70,7 +72,7 @@ change based on its name. .. group-tab:: MacOS - :: + .. code-block:: python3.8 -m venv .venv source .venv/bin/activate diff --git a/docs/tutorials/virtual-tennis/window.rst b/docs/tutorials/virtual-tennis/window.rst index 5176dd2f..55aa5e0d 100644 --- a/docs/tutorials/virtual-tennis/window.rst +++ b/docs/tutorials/virtual-tennis/window.rst @@ -2,3 +2,85 @@ Opening a Window =============================== +So we've installed everything we need, but it's always a good idea to make +sure our environment is right before moving on. A good first step for any video +game is to make sure you can make an empty window. + +Inside your `project directory`_ we need to create a file. Do so using your +code editor, and call it ``main.py``. Make sure to open it so we can add code +to it. + +.. note:: We're using ``main.py`` here, but like the name of your virtual + environment, this is just convention. If you change it, make sure to replace + the name ``main.py`` in any console commands shown later. We do suggest + keeping the name, though. + +If you haven't already, open up ``main.py`` in your code editor. Inside, add +the following code: + +.. code-block:: python + :caption: main.py + :linenos: + + import ppb + + ppb.run() + +Save this file and go back to your terminal. There, you should enter the +following command to run your game. + +.. code-block:: + :caption: Terminal + + > python main.py + +You should have a window open that looks like this: + +(Add image.) + +To run any python script (not just our ``main.py``) you call ``python``, add a +space and then the name of the script you're wanting to run. There's lots of +other options, but this is all you need to know so far. + +Before we continue, we're going to do one more thing. The default resolution of +800x600 is great, but you might want a bigger (or smaller) window. We're going +to add a constant value and give that to ppb to tell it how big of a window we +want. + +.. code-block:: + :caption: main.py + :linenos: + :emphasize-lines: 3,5 + + import ppb + + RESOLUTION = (1200, 900) + + ppb.run(resolution=RESOLUTION) + +Save this and rerun it and the screen should be bigger this time. + +The reason ``RESOLUTION`` is spelled with all caps is because this is a what +programmers call a constant. As a community, Python developers use `special +capitalization rules`_ to tell the difference between different kinds of +variables. The value is what we call a tuple, which is collection of values +that can't be changed. These values are the width and height of the window in +screen pixels. + +Just defining this value isn't enough. The :class:`ppb.GameEngine` doesn't look +for values, you have to tell it what you want. In this case the keyword argument +`resolution` is how you inform ``ppb`` what you want. So in this case, +``resolution=RESOLUTION`` is giving our constant to the engine to change the +size of the window. + +You can change either the width or the height in ``RESOLUTION`` to find a +window size you like. The Atari 2600 had a maximum resolution of 160x192, but +this is exceptionally small on modern screens. It's better to pick bigger, we +can manipulate the size of the things on the screen later. When you change the +value, you should use ``python main.py`` again to see the result. Keep experimenting + +Once you've found a screen size and shape you like, we can move on to putting +something on screen. + +.. _project directory: ../setup +.. _special capitalization rules: https://www.python.org/dev/peps/pep-0008/ From 97594fca01bd00003f79e595275ee3abb3402dfd Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Sun, 28 Mar 2021 12:01:07 -0700 Subject: [PATCH 04/11] In progress draft of section 2: Making a ball. --- docs/tutorials/virtual-tennis/ball.rst | 176 ++++++++++++++++++++++++ docs/tutorials/virtual-tennis/index.rst | 2 +- 2 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 docs/tutorials/virtual-tennis/ball.rst diff --git a/docs/tutorials/virtual-tennis/ball.rst b/docs/tutorials/virtual-tennis/ball.rst new file mode 100644 index 00000000..8505e65b --- /dev/null +++ b/docs/tutorials/virtual-tennis/ball.rst @@ -0,0 +1,176 @@ +============================================ +A Ball That Bounces +============================================ + +1. Sprites + 1. vectors + 2. Rendering + 3. events +2. setup function +3. Basic collision detection +4. Reflections + +Our next major step is to create a ball. The ball should move a little each +frame, bounce off the edges of the screen, and look like a ball. In order to do +that we'll need to create a :class:`~ppb.Sprite``, then put a copy of that +sprite into the game :class:`~ppb.Scene`. + +.. todo:: Explain basic object orientation + +Right now, we don't need to define our own scene, ppb provides one for us when +we call :func:`~ppb.run`. The run function does accept a function argument that +lets us initialize this first scene. + +.. code-block:: + :caption: main.py + :linenos: + :emphasize-lines: 3,4,6 + + RESOLUTION = (1200, 900) + + def setup(scene): + scene.background_color = (0, 0, 0) + + ppb.run(setup, resolution=RESOLUTION) + +In this step, we will set the background color of our scene object to pure +black. This better matches our example game, and demonstrates writing a +function. + +Additionally, we've added the setup function as an argument to the call of the +ppb.run function. With that in place, let's explore :class:`~ppb.Sprite`. + +Let's start by using the default sprite class directly: + +.. code-block:: + :caption: main.py + :linenos: + :emphasize-lines: 3 + + def setup(scene): + scene.background_color = (0, 0, 0) + scene.add(ppb.Sprite(image=ppb.Circle(255, 255, 255), size=1)) + +The :class:`~ppb.Sprite` does a lot of heavy lifting for us. Once added to a +running scene, it'll display its image at its location on the screen. If you run +your main script now, you should see a black background with a white circle in +the center. The size parameter allows us to adjust the size of the object on +screen. If you want the ball bigger (or smaller!) you can adjust this parameter. + +.. todo:: Explain the __init__ + +So we now have a ball that looks like a ball, but it doesn't move. So we're +going to need to edit this code. First, let's define our first class. + +.. code-block:: + :caption: main.py + :linenos: + :emphasize-lines: 4-6, 10 + + RESOLUTION = (800, 600) + + + class Ball(ppb.Sprite): + image = ppb.Circle(255, 255, 255) + size = 1 + + + def setup(scene): + scene.background_color = (0, 0, 0) + scene.add(Ball()) + +Run your program again and you'll note that nothing should have changed from +our last run. This version is functionally identical to our last step. Let's +talk about what's going on in this block now: + +The `class` keyword tells Python we're creating a class, a type of blue print +for things we put in our game. The `Ball` is a name we give our class, you can +name yours something different, but letting yourself know the class is for the +tennis ball is good practice. Inside the parentheses we're telling python that +this class is based on the :class:`ppb.Sprite` class. This lets us share some +code and not write it ourselves. + +Below that definition, you'll notice the indents, and we assigned some +variables. These variables are special and called class attributes. We can use +these as defaults for every object we make using this class. Combined with the +initialization code from ppb, it gives us a very powerful way to customize +objects. + +The next step is to get our ball moving. To do this, we're going to use vectors +and integration. (Don't worry, you won't need to know how these work, ppb +handles much of the work for us.) + +We use vectors in ppb for the position of our :class:`~ppb.Sprite ` and +in this case will also use it for a velocity vector. To do so, we'll set a +default velocity of `ppb.Vector(0, 0)` (this would be a ball that isn't moving, +like the one we already have) and then we'll use the velocity vector to move the +position of the ball each time we step through the simulation. + +.. code-block:: + :caption: main.py + :linenos: + + class Ball(ppb.Sprite): + image = ppb.Circle(255, 255, 255) + size = 1 + velocity = ppb.Vector(0, 0) + +This is a small change, and just like last time, doesn't change the behavior. +To change that, we're going to want to respond to events. + +In ppb, events are what drive all the action. The most important event is the +:class:`~ppb.events.Update` event, which happens about sixty times per second +by default. To respond to any event, you need to write a method (a special kind +of function attached to a class) that looks like this: + +.. code-block:: + + def on_update(self, event, signal): + self.do_the_thing() + +All event handlers use this pattern. The name of these methods is important: +`ppb` always looks for a method named 'on' followed by an underscore and the +name of the event in snake case. In the case of `Update` this looks like +`on_update`, but for a longer name, like the `PreRender` event it would look +like `on_pre_render`. + +So to get our ball moving, we'll write one of these handlers in our `Ball` +class. + +.. code-block:: + :caption: main.py + :linenos: + :emphasize-lines: 6, 7 + + class Ball(ppb.Sprite): + image = ppb.Circle(255, 255, 255) + size = 1 + velocity = ppb.Vector(0, 0) + + def on_update(self, event, signal): + self.position += self.velocity * event.time_delta + + def setup(scene): + +This function is called each time an update event happens, and the ball adds its +velocity (often a measurement of change in position per second) and multiplies +it by the update event's time_delta attribute so that we only apply as much +velocity as is relevant in that time period. If we just added velocity to +position our ball would move almost 60 times faster than intended. + +If you run it again, you'll see we still haven't changed what the program does. + +Let's finally make it happen: + +.. code-block:: + :caption: main.py + :linenos: + :emphasize-lines: 3 + + def setup(scene): + scene.background_color = (0, 0, 0) + scene.add(Ball(velocity=ppb.directions.Left)) + +And now our ball is moving on screen! This is very slow for now, that's +intentional, but this does demonstrate the ppb.directions module, which has a +bunch of length 1 vectors for you to use. \ No newline at end of file diff --git a/docs/tutorials/virtual-tennis/index.rst b/docs/tutorials/virtual-tennis/index.rst index 5487a4b0..5ce484c0 100644 --- a/docs/tutorials/virtual-tennis/index.rst +++ b/docs/tutorials/virtual-tennis/index.rst @@ -9,6 +9,7 @@ Virtual Tennis setup window + ball In this tutorial, we're going to build a game virtual tennis game in the vein of Pong_. We're going to go through the whole process: planning our approach, @@ -63,7 +64,6 @@ our project. ( The following will be deleted before final publication.) -1. A window 2. A ball that bounces on the edges of the screen. 3. A player paddle that can be moved. 4. Collision between player paddle and ball. From 99872205bfdab586d4dde9e7d7c807aaf44d5522 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Wed, 19 Jan 2022 20:09:37 -0800 Subject: [PATCH 05/11] Fix bad link to Anaconda blog with intersphinx. --- docs/conf.py | 1 + docs/getting-started.rst | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index dd31366a..b7791583 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -187,6 +187,7 @@ intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), + 'miniconda': ('https://docs.conda.io/en/latest/', None), } # -- Options for todo extension ---------------------------------------------- diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 31448cc4..c95c5c32 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -15,8 +15,7 @@ the `Python.org tutorial `_ or Additionally, you need to have Python 3.7 or later on your machine. You can install this via `Python.org `_ or -`Anaconda `_ -whichever is more comfortable for you. +:doc:`Anaconda ` whichever is more comfortable for you. Installing ppb From 397d476e99667e26f9ff234a78775ac8a9959f97 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Wed, 19 Jan 2022 20:43:50 -0800 Subject: [PATCH 06/11] Add Ubuntu instructions to setup. --- docs/tutorials/virtual-tennis/setup.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/virtual-tennis/setup.rst b/docs/tutorials/virtual-tennis/setup.rst index 6d3df74a..ecb7855b 100644 --- a/docs/tutorials/virtual-tennis/setup.rst +++ b/docs/tutorials/virtual-tennis/setup.rst @@ -27,7 +27,8 @@ So the first thing you need to do is open your terminal. .. group-tab:: Ubuntu - (fill out later) + Your default terminal is likely called Terminal, but if you search + for your version of linux and terminal you will find a specific one. With your terminal open, you're going to want to navigate to the ``/path/to/src/``. After that, we'll set up a project directory, and then @@ -80,7 +81,11 @@ change based on its name. .. group-tab:: Ubuntu - (add later) + .. code-block:: + + python3.8 -m venv .venv + source .venv/bin/activate + python -m pip install ppb The last step will depend on the code editor you've picked. If you're using an IDE (PyCharm, VSCode, or similar) you'll want to open your project in your IDE. From 92458f687047459079bdaf77065fc8ee3ea647c5 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Wed, 19 Jan 2022 20:44:29 -0800 Subject: [PATCH 07/11] Minor touchups to window section of virtual tennis --- docs/tutorials/virtual-tennis/window.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/tutorials/virtual-tennis/window.rst b/docs/tutorials/virtual-tennis/window.rst index 55aa5e0d..b9bd90ef 100644 --- a/docs/tutorials/virtual-tennis/window.rst +++ b/docs/tutorials/virtual-tennis/window.rst @@ -6,7 +6,7 @@ So we've installed everything we need, but it's always a good idea to make sure our environment is right before moving on. A good first step for any video game is to make sure you can make an empty window. -Inside your `project directory`_ we need to create a file. Do so using your +Inside your :doc:`project directory ` we need to create a file. Do so using your code editor, and call it ``main.py``. Make sure to open it so we can add code to it. @@ -32,7 +32,7 @@ following command to run your game. .. code-block:: :caption: Terminal - > python main.py + python main.py You should have a window open that looks like this: @@ -45,7 +45,8 @@ other options, but this is all you need to know so far. Before we continue, we're going to do one more thing. The default resolution of 800x600 is great, but you might want a bigger (or smaller) window. We're going to add a constant value and give that to ppb to tell it how big of a window we -want. +want. We'll also add a title to our game, which shows up in the title bar of +the window we create. .. code-block:: :caption: main.py @@ -56,9 +57,10 @@ want. RESOLUTION = (1200, 900) - ppb.run(resolution=RESOLUTION) + ppb.run(resolution=RESOLUTION, title="Hello Window!") -Save this and rerun it and the screen should be bigger this time. +Save this and rerun it and the screen should be bigger this time and say +"Hello Window!" on the top. The reason ``RESOLUTION`` is spelled with all caps is because this is a what programmers call a constant. As a community, Python developers use `special @@ -82,5 +84,4 @@ value, you should use ``python main.py`` again to see the result. Keep experimen Once you've found a screen size and shape you like, we can move on to putting something on screen. -.. _project directory: ../setup .. _special capitalization rules: https://www.python.org/dev/peps/pep-0008/ From fa54f22492e81de59da86b7dff8a18fdfe653d9a Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Wed, 19 Jan 2022 21:58:00 -0800 Subject: [PATCH 08/11] Add example for part 1 of virtual tennis tutorial --- examples/virtual_tennis/part_1_screen/main.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 examples/virtual_tennis/part_1_screen/main.py diff --git a/examples/virtual_tennis/part_1_screen/main.py b/examples/virtual_tennis/part_1_screen/main.py new file mode 100644 index 00000000..243e0efb --- /dev/null +++ b/examples/virtual_tennis/part_1_screen/main.py @@ -0,0 +1,5 @@ +import ppb + +RESOLUTION = (1200, 900) + +ppb.run(resolution=RESOLUTION, title="Hellow Window!") \ No newline at end of file From 63282b7e8b640573c941d870a6c232446b3106a8 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Wed, 19 Jan 2022 21:58:28 -0800 Subject: [PATCH 09/11] Finish the bouncing ball page. --- docs/tutorials/virtual-tennis/ball.rst | 124 ++++++++++++++++---- examples/virtual_tennis/part_2_ball/main.py | 37 ++++++ 2 files changed, 140 insertions(+), 21 deletions(-) create mode 100644 examples/virtual_tennis/part_2_ball/main.py diff --git a/docs/tutorials/virtual-tennis/ball.rst b/docs/tutorials/virtual-tennis/ball.rst index 8505e65b..c6511d60 100644 --- a/docs/tutorials/virtual-tennis/ball.rst +++ b/docs/tutorials/virtual-tennis/ball.rst @@ -2,36 +2,28 @@ A Ball That Bounces ============================================ -1. Sprites - 1. vectors - 2. Rendering - 3. events -2. setup function -3. Basic collision detection -4. Reflections - Our next major step is to create a ball. The ball should move a little each frame, bounce off the edges of the screen, and look like a ball. In order to do that we'll need to create a :class:`~ppb.Sprite``, then put a copy of that sprite into the game :class:`~ppb.Scene`. -.. todo:: Explain basic object orientation - Right now, we don't need to define our own scene, ppb provides one for us when we call :func:`~ppb.run`. The run function does accept a function argument that lets us initialize this first scene. .. code-block:: :caption: main.py - :linenos: - :emphasize-lines: 3,4,6 + :lineno-start: 3 + :emphasize-lines: 4-8 RESOLUTION = (1200, 900) + def setup(scene): scene.background_color = (0, 0, 0) - ppb.run(setup, resolution=RESOLUTION) + + ppb.run(setup, resolution=RESOLUTION, title="Hello Window!") In this step, we will set the background color of our scene object to pure black. This better matches our example game, and demonstrates writing a @@ -44,13 +36,16 @@ Let's start by using the default sprite class directly: .. code-block:: :caption: main.py - :linenos: + :lineno-start: 6 :emphasize-lines: 3 def setup(scene): scene.background_color = (0, 0, 0) scene.add(ppb.Sprite(image=ppb.Circle(255, 255, 255), size=1)) + + ppb.run(setup, resolution=RESOLUTION, title="Hellow Window!") + The :class:`~ppb.Sprite` does a lot of heavy lifting for us. Once added to a running scene, it'll display its image at its location on the screen. If you run your main script now, you should see a black background with a white circle in @@ -64,8 +59,8 @@ going to need to edit this code. First, let's define our first class. .. code-block:: :caption: main.py - :linenos: - :emphasize-lines: 4-6, 10 + :lineno-start: 3 + :emphasize-lines: 4-6, 11 RESOLUTION = (800, 600) @@ -108,20 +103,33 @@ position of the ball each time we step through the simulation. .. code-block:: :caption: main.py - :linenos: + :lineno-start: 6 + :emphasize-lines: 4 class Ball(ppb.Sprite): image = ppb.Circle(255, 255, 255) size = 1 velocity = ppb.Vector(0, 0) + + def setup(scene): + This is a small change, and just like last time, doesn't change the behavior. To change that, we're going to want to respond to events. +.. note:: + So vectors can be complicated if you've never used them before, but ppb + does a lot so you can ignore the specifics of the math. Just know that the + first number in the vector (called the x component) represents a change from + left-to-right or right-to-left. The second number (the y component) + represents up and down. Additionally, you can perform some useful + mathematical operations on them. + In ppb, events are what drive all the action. The most important event is the :class:`~ppb.events.Update` event, which happens about sixty times per second by default. To respond to any event, you need to write a method (a special kind -of function attached to a class) that looks like this: +of function attached to a class) that looks like this (don't write this in +your file!): .. code-block:: @@ -139,7 +147,7 @@ class. .. code-block:: :caption: main.py - :linenos: + :lineno-start: 6 :emphasize-lines: 6, 7 class Ball(ppb.Sprite): @@ -150,6 +158,7 @@ class. def on_update(self, event, signal): self.position += self.velocity * event.time_delta + def setup(scene): This function is called each time an update event happens, and the ball adds its @@ -164,7 +173,7 @@ Let's finally make it happen: .. code-block:: :caption: main.py - :linenos: + :lineno-start: 15 :emphasize-lines: 3 def setup(scene): @@ -173,4 +182,77 @@ Let's finally make it happen: And now our ball is moving on screen! This is very slow for now, that's intentional, but this does demonstrate the ppb.directions module, which has a -bunch of length 1 vectors for you to use. \ No newline at end of file +bunch of length 1 vectors for you to use. + +If you watch for a bit, the ball will wander right off the left hand side of +the screen. This is pong, though, so we're going to want to bounce off the +walls and ceiling. To do that, we're going to add a check to make sure the ball +is still inside the camera. + +.. admonition:: Camera? + + I know, the camera is a new concept, but all you need to know is the camera + helps ppb figure out what in your scene needs to get drawn to the screen + and it has sides we can use to measure where the ball is. + +Before we move our ball each frame, we're going to check if any side of the +square around our ball (this is called an axis aligned bounding box and ppb +gives us this for free) is beyond the same wall of the camera's view. So +top-to-top, left-to-left and so on. + +.. code-block:: + :caption: main.py + :lineno-start: 11 + :emphasize-lines: 2-18 + + def on_update(self, event, signal): + camera = event.scene.main_camera + reflect = ppb.Vector(0, 0) + + if self.left < camera.left: + reflect += ppb.directions.Right + + if self.right > camera.right: + reflect += ppb.directions.Left + + if self.top > camera.top: + reflect += ppb.directions.Down + + if self.bottom < camera.bottom: + reflect += ppb.directions.Up + + if reflect: + self.velocity = self.velocity.reflect(reflect.normalize()) + self.position += self.velocity * event.time_delta + +This was a lot of code in one shot, but don't worry, I'll explain. +First, we get the scene's camera. Inside of an event handler, you can +always access the current scene with `event.scene`. All scenes get a +camera, which you can get with `scene.main_camera`. Here, we store that camera +in a variable called camera. This makes it easier to type the rest of this +routine. + +Next, we set up a reflect vector. What we're trying to create is something +called a surface normal. You can think of it as an arrow pointing straight +away from an object. For example a tabletop has a surface normal that points +straight up. + +In our case, there are four surfaces we care about: the four walls of the +camera. (They're not actually walls, and you saw previously!) When the +camera reaches any edge, measured when the side of the ball goes past the value +for that wall, the surface normal is pointing the opposite way. + +We add all of the relevant normals together, and then check if they're greater +than 0. If they are, we set our velocity to our velocity vector reflected +across our reflect vector normalized. + +.. note:: + A vector with no length (specifically ``ppb.Vector(0, 0)``) is called the + zero vector. We can use this property to our advantage and only do a + reflection when we have a vector to work with. + +With this in place, you have a bouncing ball, the first major component of our +virtual tennis game! Before moving on, go ahead and try changing the initial +velocity vector (inside the setup function) by using different directions and +multiplying it by different values. You can also experiment with changing the +size of the ball and changing the colors. diff --git a/examples/virtual_tennis/part_2_ball/main.py b/examples/virtual_tennis/part_2_ball/main.py new file mode 100644 index 00000000..1c1af394 --- /dev/null +++ b/examples/virtual_tennis/part_2_ball/main.py @@ -0,0 +1,37 @@ +import ppb + +RESOLUTION = (1200, 900) + + +class Ball(ppb.Sprite): + image = ppb.Circle(255, 255, 255) + size = 1 + velocity = ppb.Vector(0, 0) + + def on_update(self, event, signal): + camera = event.scene.main_camera + reflect = ppb.Vector(0, 0) + + if self.left < camera.left: + reflect += ppb.directions.Right + + if self.right > camera.right: + reflect += ppb.directions.Left + + if self.top > camera.top: + reflect += ppb.directions.Down + + if self.bottom < camera.bottom: + reflect += ppb.directions.Up + + if reflect: + self.velocity = self.velocity.reflect(reflect.normalize()) + self.position += self.velocity * event.time_delta + + +def setup(scene): + scene.background_color = (0, 0, 0) + scene.add(Ball(velocity=ppb.directions.UpAndLeft * 3)) + + +ppb.run(setup, resolution=RESOLUTION, title="Hellow Window!") \ No newline at end of file From a31b66277d8dea283ceb6ba92a5fb12f87fca8c3 Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Wed, 19 Jan 2022 22:00:18 -0800 Subject: [PATCH 10/11] Fix highlighting in example 1 of ball --- docs/tutorials/virtual-tennis/ball.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/virtual-tennis/ball.rst b/docs/tutorials/virtual-tennis/ball.rst index c6511d60..e976b090 100644 --- a/docs/tutorials/virtual-tennis/ball.rst +++ b/docs/tutorials/virtual-tennis/ball.rst @@ -14,7 +14,7 @@ lets us initialize this first scene. .. code-block:: :caption: main.py :lineno-start: 3 - :emphasize-lines: 4-8 + :emphasize-lines: 4-7 RESOLUTION = (1200, 900) From 8fd61330c68af5b4f21caa2892efcd0b194482bb Mon Sep 17 00:00:00 2001 From: Piper Thunstrom Date: Sat, 9 Dec 2023 19:24:08 -0800 Subject: [PATCH 11/11] Update docs/tutorials/virtual-tennis/index.rst Co-authored-by: Jamie Bliss --- docs/tutorials/virtual-tennis/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/virtual-tennis/index.rst b/docs/tutorials/virtual-tennis/index.rst index 5ce484c0..d4506370 100644 --- a/docs/tutorials/virtual-tennis/index.rst +++ b/docs/tutorials/virtual-tennis/index.rst @@ -16,8 +16,8 @@ of Pong_. We're going to go through the whole process: planning our approach, breaking out individual tasks, setting up our environment, and coding. Before you start writing code on a project, it's best to think about the game -we're trying to make. For research, go try this implementation of -`Pong `_ on the internet +we're trying to make. For research, go try `this implementation of +Pong `_ on the internet archive. Let's think about what's going on in this version: