Interactive Sprite Widget
interactive_sprite_widget.py
1"""
2Interactive Sprite Widget
3
4Demonstrates UIInteractiveSpriteWidget — making sprites clickable
5inside the Arcade UI system with hover and press feedback.
6
7Click a gem to score a point. Gems light up on hover and
8shrink when pressed.
9
10If Python and Arcade are installed, this example can be run from the
11command line with:
12python -m arcade.examples.interactive_sprite_widget
13"""
14
15import arcade
16from arcade.color import TRANSPARENT_BLACK
17from arcade.gui import UIManager, UIInteractiveSpriteWidget
18from arcade.gui.property import bind
19from arcade.gui.surface import Surface
20from arcade.gui.widgets.layout import UIBoxLayout, UIAnchorLayout
21
22WINDOW_WIDTH = 800
23WINDOW_HEIGHT = 600
24WINDOW_TITLE = "Interactive Sprite Widget Example"
25
26GEM_IMAGES = [
27 ":resources:images/items/gemBlue.png",
28 ":resources:images/items/gemGreen.png",
29 ":resources:images/items/gemRed.png",
30 ":resources:images/items/gemYellow.png",
31]
32GEM_SCALE = 0.75
33PRESS_SHRINK = 0.85
34
35
36class PressableGemWidget(UIInteractiveSpriteWidget):
37 """A gem that visually shrinks when pressed, without affecting layout."""
38
39 def do_render(self, surface: Surface):
40 self.prepare_render(surface)
41 surface.clear(color=TRANSPARENT_BLACK)
42 if self._sprite is not None:
43 if self.pressed:
44 draw_width = self.width * PRESS_SHRINK
45 draw_height = self.height * PRESS_SHRINK
46 offset_x = (self.width - draw_width) / 2
47 offset_y = (self.height - draw_height) / 2
48 surface.draw_sprite(offset_x, offset_y, draw_width, draw_height, self._sprite)
49 else:
50 surface.draw_sprite(0, 0, self.width, self.height, self._sprite)
51
52
53class GameView(arcade.View):
54
55 def __init__(self):
56 super().__init__()
57 self.ui_manager = UIManager()
58 self.score = 0
59 self.score_display = None
60 self.background_color = arcade.color.DARK_BLUE_GRAY
61
62 def setup(self):
63 self.score = 0
64 self.score_display = arcade.Text(
65 "Score: 0", 10, WINDOW_HEIGHT - 30,
66 arcade.color.WHITE, font_size=18,
67 )
68
69 gem_row = UIBoxLayout(vertical=False, space_between=30)
70
71 for image_path in GEM_IMAGES:
72 sprite = arcade.Sprite(image_path, scale=GEM_SCALE)
73 widget = PressableGemWidget(sprite=sprite)
74
75 def make_hover_callback(wgt, spr):
76 def on_hover_change(instance):
77 if wgt.hovered:
78 spr.color = (220, 220, 255)
79 else:
80 spr.color = (255, 255, 255)
81 return on_hover_change
82 bind(widget, "hovered", make_hover_callback(widget, sprite))
83
84 def make_click_callback(path):
85 def on_click(event):
86 self.score += 1
87 self.score_display.text = f"Score: {self.score}"
88 return on_click
89 widget.on_click = make_click_callback(image_path)
90
91 gem_row.add(widget)
92
93 anchor = UIAnchorLayout(width=WINDOW_WIDTH, height=WINDOW_HEIGHT, size_hint=None)
94 anchor.add(gem_row, anchor_x="center", anchor_y="center")
95 self.ui_manager.add(anchor)
96
97 def on_show_view(self):
98 self.ui_manager.enable()
99
100 def on_hide_view(self):
101 self.ui_manager.disable()
102
103 def on_draw(self):
104 self.clear()
105 self.ui_manager.draw()
106 self.score_display.draw()
107
108
109def main():
110 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
111 view = GameView()
112 window.show_view(view)
113 view.setup()
114 arcade.run()
115
116
117if __name__ == "__main__":
118 main()