summaryrefslogtreecommitdiffhomepage
path: root/samples/19_lowrez_jam_01_hello_world/app/main.rb
blob: 1181785b7d67657e070e8d78bd242ead580036ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
=begin

 Reminders:

 - args.outputs.lines: An array. The values generate a line.
   The parameters are [X1, Y1, X2, Y2, RED, GREEN, BLUE, ALPHA]
   For more information about lines, go to mygame/documentation/04-lines.md.

   In this sample app, we're using lines to create the grid lines that make
   a 64x64 grid.

 - args.outputs.labels: An array. The values generate a label.
   The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
   For more information about labels, go to mygame/documentation/02-labels.md.

 - args.outputs.sprites: An array. The values generate a sprite.
   The parameters are [X, Y, WIDTH, HEIGHT, IMAGE PATH]
   For more information about sprites, go to mygame/documentation/05-sprites.md.

 - args.outputs.solids: An array. The values generate a solid.
   The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
   For more information about solids, go to mygame/documentation/03-solids-and-borders.md.

 - String interpolation: Uses #{} syntax; everything between the #{ and the } is evaluated
   as Ruby code, and the placeholder is replaced with its corresponding value or result.

 - args.state.new_entity: Used when we want to create a new object, like a sprite or button.
   For example, if we want to create a new button, we would declare it as a new entity and
   then define its properties. (Remember, you can use state to define ANY property and it will
   be retained across frames.)

 - num1.idiv(num2): Divides two numbers and returns an integer.

 - num1.fdiv(num2): Divides two numbers and returns a float (has a decimal).

 - args.click.point.(x|y): The x and y location of the mouse.
   For more information about the mouse, go to mygame/documentation/07-mouse.md.

 - Symbol (:): Ruby object with a name and an internal ID. Symbols are useful
   because with a given symbol name, you can refer to the same object throughout
   a Ruby program.

=end

# https://twitter.com/hashtag/LOWREZJAM

# Sets sprite, label, and solid definitions and adds them to appropriate collections
def lowrez_tick args, lowrez_sprites, lowrez_labels, lowrez_borders, lowrez_solids, lowrez_mouse
  args.state.show_gridlines = true # shows gridlines; change to false and they won't be visible

  # Iterates through the images in the sprites folder using string interpolation
  # There are 6 pngs that represent the full animation
  # Each png is shown for 4 frames
  # The animation should loop forever (true)
  lowrez_sprites << [0, 0, 64, 64, "sprites/explosion_#{0.frame_index 6, 4, true}.png"]

  # Creates labels of alphabet in different positions and colors
  lowrez_labels  << [0, 0,  "ABCDEFGHIJKLM", 255,   0,   0] # red label
  lowrez_labels  << [0, 29, "ABCDEFGHIJKLM",   0, 255,   0] # green label
  lowrez_labels  << [0, 60, "ABCDEFGHIJKLM",   0,   0, 255, 255] # blue label

  #Creates a solid black background for the 64x64 canvas
  args.render_target(:lowrez).solids << [0, 0, 64, 64, 255, 255, 255]
end

###################################################################################
# YOU CAN PLAY AROUND WITH THE CODE BELOW, BUT USE CAUTION AS THIS IS WHAT EMULATES
# THE 64x64 CANVAS.
###################################################################################

# Sets values to produce 64x64 canvas.
# These values are not changed, which is why ||= is not used.
TINY_RESOLUTION       = 64
TINY_SCALE            = 720.fdiv(TINY_RESOLUTION) # original dimension of 720 is scaled down by 64
CENTER_OFFSET         = (1280 - 720).fdiv(2) # sets center
EMULATED_FONT_SIZE    = 20
EMULATED_FONT_X_ZERO  = 0 # increasing this value would shift labels to the right
EMULATED_FONT_Y_ZERO  = 46 # increasing shifts labels up, decreasing shifts labels down

# Creates empty collections, and calls methods needed for the game to run properly.
def tick args
  sprites = []
  labels = []
  borders = []
  solids = []
  mouse = emulate_lowrez_mouse args # calls method to set mouse to mouse's position
  args.state.show_gridlines = false # grid lines are not shown
  lowrez_tick args, sprites, labels, borders, solids, mouse # contains definitions
  render_gridlines_if_needed args # outputs grid lines if show_gridlines is true
  render_mouse_crosshairs args, mouse # outputs position of mouse using label
  emulate_lowrez_scene args, sprites, labels, borders, solids, mouse # emulates scene on screen
end

# Sets values based on the position of the mouse on the screen.
def emulate_lowrez_mouse args
  # declares mouse as a new entity and sets values for x and y variables
  args.state.new_entity_strict(:lowrez_mouse) do |m|
    # mouse's original coordinates are scaled down to match canvas
    # original coordinates are within 1280x720 dimensions
    m.x = args.mouse.x.idiv(TINY_SCALE) - CENTER_OFFSET.idiv(TINY_SCALE) - 1
    m.y = args.mouse.y.idiv(TINY_SCALE)

    if args.mouse.click # if mouse is clicked
      m.click = [ # sets definition and stores mouse click's position
        args.mouse.click.point.x.idiv(TINY_SCALE) - CENTER_OFFSET.idiv(TINY_SCALE) - 1,
        args.mouse.click.point.y.idiv(TINY_SCALE)
      ]
      m.down = m.click # down stores click's value, which is mouse click's position
    else
      m.click = nil # if no click occurred, both click and down are empty (do not store any position)
      m.down = nil
    end

    if args.mouse.up # if mouse is up (not being pressed or held down)
      m.up = [ # sets definition, stores mouse's position
        args.mouse.up.point.x.idiv(TINY_SCALE) - CENTER_OFFSET.idiv(TINY_SCALE) - 1,
        args.mouse.up.point.y.idiv(TINY_SCALE)
      ]
    else
      m.up = nil # if mouse is not in "up" state, up is empty (has no value)
    end
  end
end

# Outputs position of mouse on screen using white label
def render_mouse_crosshairs args, mouse
  return unless args.state.show_gridlines # return unless true (grid lines are showing)
  args.labels << [10, 25, "mouse: #{mouse.x} #{mouse.y}", 255, 255, 255] # string interpolation
end

# Emulates the low rez scene by adding solids, sprites, etc. to appropriate collections
# and creating labels for the characters of alphabet
def emulate_lowrez_scene args, sprites, labels, borders, solids, mouse
  args.render_target(:lowrez).solids  << [0, 0, 1280, 720] # sets black background in grid
  args.render_target(:lowrez).sprites << sprites # outputs sprites
  args.render_target(:lowrez).borders << borders # outputs borders
  args.render_target(:lowrez).solids  << solids # outputs solids

  # The font that is used is saved in the game's folder.
  # Without the .ttf file, the label would not be created correctly.
  args.outputs.primitives << labels.map do |l| # outputs all elements of labels collection as primitive
    as_label = l.label
    l.text.each_char.each_with_index.map do |char, i| # perform action on each character in labels collection
      # label definition
      # each label starts on left side of grid and places space between alphabet characters
      # centered to fit within grid dimensions
      [CENTER_OFFSET + EMULATED_FONT_X_ZERO + (as_label.x * TINY_SCALE) + i * 5 * TINY_SCALE,
       EMULATED_FONT_Y_ZERO + (as_label.y * TINY_SCALE), char,
       EMULATED_FONT_SIZE, 0, as_label.r, as_label.g, as_label.b, as_label.a, 'dragonruby-gtk-4x4.ttf'].label
    end
  end

  # placed in center; width and height are scaled down to fit canvas
  # comment this line out and the sprites do not appear, and neither does the black canvas background
  args.sprites    << [CENTER_OFFSET, 0, 1280 * TINY_SCALE, 720 * TINY_SCALE, :lowrez]

  args.primitives << [0, 0, CENTER_OFFSET, 720].solid # black background on left side of grid
  args.primitives << [1280 - CENTER_OFFSET, 0, CENTER_OFFSET, 720].solid # black on right side of grid
  args.primitives << [0, 0, 1280, 2].solid # black on bottom; change 2 to 200 and see what happens
end

def render_gridlines_if_needed args
  # if grid lines are showing and static_lines collection (which contains grid lines) is empty
  if args.state.show_gridlines && args.static_lines.length == 0
    # add to the collection by adding line definitions 65 times (because of 64x64 canvas)
    # placed at equal distance apart within grid dimensions
    args.static_lines << 65.times.map do |i|
      [
        # [starting x, starting y, ending x, ending y, red, green, blue]
        # Vertical lines have the same starting and ending x value.
        # To make the vertical grid lines look thicker and more prominent, two separators are
        # placed together one pixel apart (explains "+1" in x parameter) as one vertical grid line.
        [CENTER_OFFSET + i * TINY_SCALE + 1,  0,
         CENTER_OFFSET + i * TINY_SCALE + 1,  720,                128, 128, 128], # vertical line 1
        [CENTER_OFFSET + i * TINY_SCALE,      0,
         CENTER_OFFSET + i * TINY_SCALE,      720,                128, 128, 128], # vertical line 2
        # Horizontal lines have the same starting and ending y value.
        # The two horizontal separators that are considered one grid line are placed
        # one pixel apart (explains the "1 +" in the y parameter).
        # That is why there are four line definitions (distinguished by []) being added to static_lines.
        # Two vertical and two horizontal separators are added to create one vertical
        # and one horizontal grid line.
        [CENTER_OFFSET,                       0 + i * TINY_SCALE,
         CENTER_OFFSET + 720,                 0 + i * TINY_SCALE, 128, 128, 128], # horizontal line 1
        [CENTER_OFFSET,                       1 + i * TINY_SCALE,
         CENTER_OFFSET + 720,                 1 + i * TINY_SCALE, 128, 128, 128] # horizontal line 2
      ]
    end
  elsif !args.state.show_gridlines # if show_gridlines is false (grid lines are not showing)
    args.static_lines.clear # clear the collection so no grid lines are in it
  end
end