Skip to content

Commit

Permalink
starting basic gui implementation; some bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladar4 committed Oct 23, 2012
1 parent d02a2b5 commit bac099d
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 23 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
v0.3 (in process)
=================
* Documentation
* Graphics:
+ screen scaling
+ multi-line text
* GUI:
+ button
* Audio:
+ sound
+ music
Expand Down
90 changes: 69 additions & 21 deletions lib/collider.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import

type

TColliderType* = enum CTPoint, CTBox, CTCircle, CTMask

# Base class (virtual)
PCollider* = ref TCollider
TCollider* = object of TOBject
Expand Down Expand Up @@ -112,6 +114,8 @@ method y*(obj: PCollider): int {.inline.} = nil
method `y=`*(obj: PCollider, value: int) {.inline.} = nil

method collide*(a: PCollider, b: PCollider): bool = nil
method collide*(a: PCollider, b: TPoint): bool = nil
method collide*(a: TPoint, b: PCollider): bool = nil


# Point
Expand Down Expand Up @@ -166,6 +170,16 @@ method collide*(a: PPointCollider, b: PPointCollider): bool =
return false


method collide*(a: PPointCollider, b: TPoint): bool =
if (a.x == b.x) and (a.y == b.y):
return true
return false


method collide*(a: TPoint, b: PPointCollider): bool {.inline.} =
return collide(b, a)


# Box - Box
method collide*(a: PBoxCollider, b: PBoxCollider): bool =
if a.bottom <= b.top: return false
Expand Down Expand Up @@ -226,44 +240,78 @@ method collide*(a: PMaskCollider, b: PMaskCollider): bool =
return false


# Point - Box
method collide*(a: PPointCollider, b: PBoxCollider): bool =
if (a.x < b.left) or (a.x >= b.right): return false
if (a.y < b.top) or (a.y >= b.bottom): return false
# Box - Point
method collide*(a: PBoxCollider, b: PPointCollider): bool =
if (b.x < a.left) or (b.x >= a.right): return false
if (b.y < a.top) or (b.y >= a.bottom): return false
return true


# Box - Point
method collide*(a: PBoxCollider, b: PPointCollider): bool {.inline.} =
method collide*(a: PBoxCollider, b: TPoint): bool =
if (b.x < a.left) or (b.x >= a.right): return false
if (b.y < a.top) or (b.y >= a.bottom): return false
return true


# Point - Box
method collide*(a: PPointCollider, b: PBoxCollider): bool {.inline.} =
return collide(b, a)

method collide*(a: TPoint, b: PBoxCollider): bool {.inline.} =
return collide(b, a)

# Point - Circle
method collide*(a: PPointCollider, b: PCircleCollider): bool =
if distance((a.x, a.y), (b.centerX, b.centerY)).toInt > b.radius: return false

# Circle - Point
method collide*(a: PCircleCollider, b: PPointCollider): bool =
if distance((b.x, b.y), (a.centerX, a.centerY)).toInt > a.radius: return false
return true


# Circle - Point
method collide*(a: PCircleCollider, b: PPointCollider): bool {.inline.} =
method collide*(a: PCircleCollider, b: TPoint): bool =
if distance((b.x, b.y), (a.centerX, a.centerY)).toInt > a.radius: return false
return true


# Point - Circle
method collide*(a: PPointCollider, b: PCircleCollider): bool {.inline.} =
return collide(b, a)


# Point - Mask
method collide*(a: PPointCollider, b: PMaskCollider): bool =
var boxB: TRect
boxB = b.mask.getRect()
boxB.x = int16(boxB.x + b.x)
boxB.y = int16(boxB.y + b.y)
if not collide(a, newBoxCollider(boxB)):
method collide*(a: TPoint, b: PCircleCollider): bool {.inline.} =
return collide(b, a)


# Mask - Point
method collide*(a: PMaskCollider, b: PPointCollider): bool =
var boxA: TRect
boxA = a.mask.getRect()
boxA.x = int16(boxA.x + a.x)
boxA.y = int16(boxA.y + a.y)
if not collide(newBoxCollider(boxA), b):
return false
if b.mask.data[a.y - boxB.y][a.x - boxB.x]:
if a.mask.data[b.y - boxA.y][b.x - boxA.x]:
return true
return false


# Mask - Point
method collide*(a: PMaskCollider, b: PPointCollider): bool {.inline.} =
method collide*(a: PMaskCollider, b: TPoint): bool =
var boxA: TRect
boxA = a.mask.getRect()
boxA.x = int16(boxA.x + a.x)
boxA.y = int16(boxA.y + a.y)
if not collide(newBoxCollider(boxA), b):
return false
if a.mask.data[b.y - boxA.y][b.x - boxA.x]:
return true
return false


# Point - Mask
method collide*(a: PPointCollider, b: PMaskCollider): bool {.inline.} =
return collide(b, a)


method collide*(a: TPoint, b: PMaskCollider): bool {.inline.} =
return collide(b, a)


Expand Down
76 changes: 76 additions & 0 deletions lib/gui_button.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import
entity, sprite, input, collider, mask

type
PGUIButton* = ref TGUIButton
TGUIButton* = object of TEntity
fWasHovered, fWasPressed: bool


proc free*(obj: PGUIButton) =
PEntity(obj).free()


proc newGUIButton*(graphic: PSprite,
x: float = 0.0, y: float = 0.0,
colliderType: TColliderType = CTBox): PGUIButton =
new(result, free)
init(PEntity(result), graphic, x, y)
# set collider
case colliderType:
of CTPoint:
result.collider = newPointCollider(result.xi, result.yi)
of CTBox:
result.collider = newBoxCollider(result.getRect())
of CTCircle:
result.collider = newCircleCollider(result.getCircle())
of CTMask:
result.collider = newMaskCollider(newMask(result.graphic.surface),
result.xi, result.yi)
else: nil
# set variables
result.fWasHovered = false
result.fWasPressed = false


# Button frames in sprite must be in this order:
# 0 - default
# 1 - pressed
# 2 - hover
# 3 - hover pressed
proc updateFrame(obj: PGUIButton) =
let spr = PSprite(obj.graphic)
if obj.fWasHovered:
if obj.fWasPressed:
if spr.count > 3: spr.frame = 3
elif spr.count > 1: spr.frame = 1
else: spr.frame = 0
else:
if spr.count > 2: spr.frame = 2
else: spr.frame = 0
else:
if obj.fWasPressed:
if spr.count > 1: spr.frame = 1
else: spr.frame = 0
else:
spr.frame = 0


proc updateButton*(obj: PGUIButton) =
obj.updateEntity()
if obj.collider.collide(mousePos()): # mouse over button
if isButtonDown(1):
obj.fWasPressed = true # button pressed
elif isButtonUp(1):
obj.fWasPressed = false # button released
obj.fWasHovered = true
else: # mouse not over button
if obj.fWasPressed and isButtonUp(1): # button released
obj.fWasPressed = false
obj.fWasHovered = false
obj.updateFrame()


method update*(obj: PGUIButton) {.inline.} =
obj.updateButton()

2 changes: 1 addition & 1 deletion lib/input.nim
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ template isButtonDown*(btn: int): bool =

# check if was MOUSEBUTTONUP event of this button since last update
template isButtonUp*(btn: int): bool =
isKeyEvent(btn, up)
isButtonEvent(btn, up)


# get mouse position
Expand Down
3 changes: 2 additions & 1 deletion lib/screen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ proc loadImage*(filename: cstring): PSurface =


# blit surface preserving alpha channel
proc blitSurfaceAlpha*(src: PSurface, srcrect: PRect, dst: PSurface, dstrect: PRect): int =
proc blitSurfaceAlpha*(src: PSurface, srcrect: PRect,
dst: PSurface, dstrect: PRect): int =
check(src.setAlpha(0, 255))
result = blitSurface(src, srcrect, dst, dstRect)
check(src.setAlpha(SRCALPHA, 255))
Expand Down

0 comments on commit bac099d

Please sign in to comment.