Skip to content

Commit

Permalink
Merge branch 'shader_experimental' of https://github.com/pvcraven/arcade
Browse files Browse the repository at this point in the history
 into shader_experimental
  • Loading branch information
einarf committed Apr 17, 2020
2 parents 155bd39 + 66b4db9 commit c955ff6
Show file tree
Hide file tree
Showing 12 changed files with 354 additions and 2 deletions.
3 changes: 3 additions & 0 deletions arcade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@

from .version import VERSION

from .paths import has_line_of_sight


__all__ = ['AnimatedTimeBasedSprite',
'AnimatedTimeSprite',
Expand Down Expand Up @@ -385,6 +387,7 @@
'get_tilemap_layer',
'get_viewport',
'get_window',
'has_line_of_sight',
'is_point_in_polygon',
'isometric_grid_to_screen',
'lerp',
Expand Down
236 changes: 236 additions & 0 deletions arcade/examples/line_of_sight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
"""
Line of Sight
Artwork from http://kenney.nl
If Python and Arcade are installed, this example can be run from the command line with:
python -m arcade.examples.line_of_sight
"""

import arcade
import os
import random

SPRITE_SCALING = 0.5

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_TITLE = "Line of Sight"

MOVEMENT_SPEED = 5

VIEWPORT_MARGIN = 300

class Player(arcade.Sprite):
""" Player sprite"""
def update(self):
""" Move player """
self.center_x += self.change_x
self.center_y += self.change_y


class MyGame(arcade.Window):
"""
Main application class.
"""

def __init__(self, width, height, title):
"""
Initializer
"""

# Call the parent class initializer
super().__init__(width, height, title)

# Set the working directory (where we expect to find files) to the same
# directory this .py file is in. You can leave this out of your own
# code, but it is needed to easily run the examples using "python -m"
# as mentioned at the top of this program.
file_path = os.path.dirname(os.path.abspath(__file__))
os.chdir(file_path)

# Variables that will hold sprite lists
self.player_list = None
self.wall_list = None
self.enemy_list = None

# Set up the player info
self.player = None

# Track the current state of what key is pressed
self.left_pressed = False
self.right_pressed = False
self.up_pressed = False
self.down_pressed = False

self.physics_engine = None

# Used in scrolling
self.view_bottom = 0
self.view_left = 0

# Set the background color
arcade.set_background_color(arcade.color.AMAZON)

def setup(self):
""" Set up the game and initialize the variables. """

# Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList(use_spatial_hash=True)
self.enemy_list = arcade.SpriteList()

# Set up the player
self.player = Player(":resources:images/animated_characters/female_person/femalePerson_idle.png", SPRITE_SCALING)
self.player.center_x = 50
self.player.center_y = 350
self.player_list.append(self.player)

# Set enemies
enemy = Player(":resources:images/animated_characters/zombie/zombie_idle.png", SPRITE_SCALING)
enemy.center_x = 350
enemy.center_y = 350
self.enemy_list.append(enemy)

spacing = 200
for column in range(10):
for row in range(10):
sprite = arcade.Sprite(":resources:images/tiles/grassCenter.png", 0.5)

x = (column + 1) * spacing
y = (row + 1) * sprite.height

sprite.center_x = x
sprite.center_y = y
if random.randrange(100) > 20:
self.wall_list.append(sprite)

self.physics_engine = arcade.PhysicsEngineSimple(self.player,
self.wall_list)

def on_draw(self):
"""
Render the screen.
"""
try:
# This command has to happen before we start drawing
arcade.start_render()

# Draw all the sprites.
self.player_list.draw()
self.wall_list.draw()
self.enemy_list.draw()

for enemy in self.enemy_list:
if arcade.has_line_of_sight(self.player.position,
enemy.position,
self.wall_list):
color = arcade.color.RED
else:
color = arcade.color.WHITE
arcade.draw_line(self.player.center_x,
self.player.center_y,
enemy.center_x,
enemy.center_y,
color,
2)

except Exception as e:
print(e)

def on_update(self, delta_time):
""" Movement and game logic """

# Calculate speed based on the keys pressed
self.player.change_x = 0
self.player.change_y = 0

if self.up_pressed and not self.down_pressed:
self.player.change_y = MOVEMENT_SPEED
elif self.down_pressed and not self.up_pressed:
self.player.change_y = -MOVEMENT_SPEED
if self.left_pressed and not self.right_pressed:
self.player.change_x = -MOVEMENT_SPEED
elif self.right_pressed and not self.left_pressed:
self.player.change_x = MOVEMENT_SPEED

self.physics_engine.update()

# --- Manage Scrolling ---

# Keep track of if we changed the boundary. We don't want to call the
# set_viewport command if we didn't change the view port.
changed = False

# Scroll left
left_boundary = self.view_left + VIEWPORT_MARGIN
if self.player.left < left_boundary:
self.view_left -= left_boundary - self.player.left
changed = True

# Scroll right
right_boundary = self.view_left + SCREEN_WIDTH - VIEWPORT_MARGIN
if self.player.right > right_boundary:
self.view_left += self.player.right - right_boundary
changed = True

# Scroll up
top_boundary = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN
if self.player.top > top_boundary:
self.view_bottom += self.player.top - top_boundary
changed = True

# Scroll down
bottom_boundary = self.view_bottom + VIEWPORT_MARGIN
if self.player.bottom < bottom_boundary:
self.view_bottom -= bottom_boundary - self.player.bottom
changed = True

# Make sure our boundaries are integer values. While the view port does
# support floating point numbers, for this application we want every pixel
# in the view port to map directly onto a pixel on the screen. We don't want
# any rounding errors.
self.view_left = int(self.view_left)
self.view_bottom = int(self.view_bottom)

# If we changed the boundary values, update the view port to match
if changed:
arcade.set_viewport(self.view_left,
SCREEN_WIDTH + self.view_left,
self.view_bottom,
SCREEN_HEIGHT + self.view_bottom)

def on_key_press(self, key, modifiers):
"""Called whenever a key is pressed. """

if key == arcade.key.UP:
self.up_pressed = True
elif key == arcade.key.DOWN:
self.down_pressed = True
elif key == arcade.key.LEFT:
self.left_pressed = True
elif key == arcade.key.RIGHT:
self.right_pressed = True

def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """

if key == arcade.key.UP:
self.up_pressed = False
elif key == arcade.key.DOWN:
self.down_pressed = False
elif key == arcade.key.LEFT:
self.left_pressed = False
elif key == arcade.key.RIGHT:
self.right_pressed = False


def main():
""" Main method """
window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
window.setup()
arcade.run()


if __name__ == "__main__":
main()
6 changes: 5 additions & 1 deletion arcade/examples/sprite_move_scrolling.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ def __init__(self, width, height, title):

# Sprite lists
self.player_list = None
self.coin_list = None

# Set up the player
self.player_sprite = None

self.coin_list = None
self.wall_list = None

self.physics_engine = None

# Used in scrolling
self.view_bottom = 0
self.view_left = 0

Expand Down
41 changes: 41 additions & 0 deletions arcade/paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Path-related functions.
"""
from arcade import Point
from arcade import SpriteList
from arcade import get_distance
from arcade import lerp_vec
from arcade import get_sprites_at_point

def has_line_of_sight(point_1: Point,
point_2: Point,
walls: SpriteList,
max_distance: int = -1,
check_resolution: int = 2):
"""
Determine if we have line of sight between two points. Try to make sure
that spatial hashing is enabled on the wall SpriteList or this will be
very slow.
:param Point point_1: Start position
:param Point point_2: End position position
:param SpriteList walls: List of all blocking sprites
:param int max_distance: Max distance point 1 can see
:param int check_resolution: Check every x pixels for a sprite. Trade-off
between accuracy and speed.
"""
distance = get_distance(point_1[0], point_1[1],
point_2[0], point_2[1])
steps = int(distance // check_resolution)
for step in range(steps + 1):
step_distance = step * check_resolution
u = step_distance / distance
midpoint = lerp_vec(point_1, point_2, u)
if max_distance != -1 and step_distance > max_distance:
return False
# print(point_1, point_2, step, u, step_distance, midpoint)
sprite_list = get_sprites_at_point(midpoint, walls)
if len(sprite_list) > 0:
return False
return True
7 changes: 7 additions & 0 deletions doc/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,13 @@ Basic Platformers

:ref:`platformer_tutorial`

.. figure:: thumbs/line_of_sight.png
:figwidth: 170px

:ref:`line_of_sight`



Using Tiled Map Editor to Create Maps
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
Binary file added doc/examples/line_of_sight.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions doc/examples/line_of_sight.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
:orphan:

.. _line_of_sight:

Line of Sight
==================================

.. image:: line_of_sight.png
:width: 600px
:align: center
:alt: Line of Sight

.. literalinclude:: ../../arcade/examples/line_of_sight.py
:caption: line_of_sight.py
:linenos:
3 changes: 3 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Version 2.4 has:
* Physics engine is less likely to 'glitch' out
* Antialiasing should now work on windows if ``antialiasing=True``
is passed in the window constructor.
* Added `arcade.get_display_size` to get resolution of the monitor
* Added `Window.center_window()` to center the window on the monitor.
* Add support for `has_line_of_sight()`

Version 2.3.15
--------------
Expand Down
Binary file added issue_630_2/sounds/warpout.ogg.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions tests/unit2/test_drawing_primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,6 @@ def on_draw(self):
def test_main():
""" Main method """
window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT)
window.center_window()
window.test()
window.close()

0 comments on commit c955ff6

Please sign in to comment.