Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

A Clock made with Gosu...

Well, I started yesterday to make this script to create a clock with a digital watch underneath and today I can show you 2 screenshots that should convince you of using Gosu for its simple way to deal with anything in general.

You may find my example script at the bottom of this post.

SCREENSHOTS

kyowatchgosuscreenshot.png


kyowatchcalgosu.png

[rgss]#!/usr/bin/env ruby
# KyoWatch Gosu version
# by Kyonides-Arkanthos
# 12.23.2009
# Tools:  Gosu gem for Linux
require 'rubygems'
require 'gosu'
module ZOrder
    UI = 3
end
 
module KyoVocab
  KyoX, KyoY = 200, 168
  YearRangeMIN = 1990
  YearRangeMAX = 2020
  KyoDay       = { 'AM' => [6,7,8,9,10,11], 'PM' => [1,2,3,4,5,12] }
  KyoDayFullNames = {
      nil => '---------', 0 => 'Sunday',    1 => 'Monday',  
      2 => 'Tuesday',     3 => 'Wednesday', 4 => 'Thursday',
      5 => 'Friday',      6 => 'Saturday'
    }
  KyoDayPartialNames = {
      nil => '---', 0 => 'SUN', 1 => 'MON', 2 => 'TUE',
      3 => 'WED',   4 => 'THU', 5 => 'FRI', 6 => 'SAT'
    }
  KyoMonthFullNames = { 0 => '----------',
       1 => 'January',  2 => 'February',  3 => 'March',
       4 => 'April',    5 => 'May',       6 => 'June',
       7 => 'July',     8 => 'August',    9 => 'September',
      10 => 'October', 11 => 'November', 12 => 'December'
    }
  KyoMonthPartialNames = { 0 => '---',
       1 => 'JAN',  2 => 'FEB',  3 => 'MAR',
       4 => 'APR',  5 => 'MAY',  6 => 'JUN',
       7 => 'JUL',  8 => 'AUG',  9 => 'SEP',
      10 => 'OCT', 11 => 'NOV', 12 => 'DEC'
    }
  REGYEAR  = [nil,31,28,31,30,31,30,31,31,30,31,30,31]
  LEAPYEAR = [nil,31,29,31,30,31,30,31,31,30,31,30,31]
  REGYEARMOD  = {
    1 => 0, 2 => 3, 3 => 3, 4 => 6, 5 => 1, 6 => 4,
    7 => 6, 8 => 2, 9 => 5, 10=> 0, 11=> 3, 12=> 5
    }
  LEAPYEARMOD = {
    1 => 0, 2 => 3, 3 => 4, 4 => 0, 5 => 2, 6 => 5,
    7 => 0, 8 => 3, 9 => 6, 10=> 1, 11=> 4, 12=> 6
    }
end
 
class KyoWatchGosu
    include Gosu, KyoVocab
  attr_accessor :kyoclock, :time_now, :frame_count, :no_clocktime, :total_sec
  attr_accessor :year, :mon, :day, :hour, :min, :sec, :dayname
  def initialize
    @frame_count = milliseconds
    @kyoclock = [0,1,0,0,0,'??',0]
        @hour    = @kyoclock[3]
        @dayname = @kyoclock[6]
    @time_now = []
    @no_clocktime = true
  end
 
  def update_clock
    @total_sec = (milliseconds-@frame_count) / 1000
    m    = @total_sec / 60 % 60
    h    = @total_sec / 60 / 60 % 24
    d    = @total_sec / 60 / 60 / 24 % 30
    mon  = @total_sec / 60 / 60 / 24 / 30 % 12
    year = @total_sec / 60 / 60 / 24 / 30 / 12
        total_min    = @kyoclock[4] + m
    total_hours  = @kyoclock[3] + h + (total_min / 60)
    total_days   = @kyoclock[2] + d + (total_hours / 24)
    total_months = @kyoclock[1] + mon + (total_days / 30)
    total_years  = @kyoclock[0] + year + (total_months / 12)
        @sec  = @total_sec % 60
        @min  = total_min % 60
    @hour = total_hours % 24
    max = !leap?(total_years) ? REGYEAR[total_months] : LEAPYEAR[total_months]
    @day  = total_days % max
    @mon  = total_months % 12
    @year = total_years
    @kyoclock[5] = 'AM' if @hour >=  0 and @min >= 0
    @kyoclock[5] = 'PM' if @hour >= 12 and @min >= 0
    @time_now = [@year, @mon, @day, @hour, @min, @kyoclock[5], @kyoclock[6]]
  end
 
  def leap?(year)
    year % 4 == 0 && year % 100 != 0 || year % 400 == 0
  end
 
  def day_name(year, month, daynum)
    @y = year-1
    @a = (@y % 7)
    @b = (  (@y/4) - ( 3*( ( (@y/100)+1 ) /4 ) )  ) % 7
    @mod = REGYEARMOD[month]  if !leap?(year)
    @mod = LEAPYEARMOD[month] if leap?(year)
    @d = daynum % 7
    @day_name = (@a + @b + @mod + @d) % 7
    return @day_name
  end
 
  def minutes
    return @time_now[4]
  end
 
  def hours
    hour = @disable_24H ? @time_now[3]%12 : @time_now[3]
    hour = 12 if @disable_24H and @time_now[3]%12 == 0
    return hour
  end
end
 
class GameWindow < Gosu::Window
    include Gosu
    attr_reader :text
    def initialize
    super(525, 260, false)
        self.caption = 'KyoWatch'
        @clockpic  = Gosu::Image.new(self, 'images/clock.png', true)
        @clocksec  = Gosu::Image.new(self, 'images/clocksec.png', true)
        @clockmin  = Gosu::Image.new(self, 'images/clockmin.png', true)
        @clockhour = Gosu::Image.new(self, 'images/clockhour.png', true)
        @fonttype = 'Digital-7'# Gosu::default_font_name
        @font1 = Font.new(self, @fonttype, 48)
        @font2 = Font.new(self, 'DeJaVu Sans Mono', 20)
        @font3 = Font.new(self, 'DeJaVu Sans Mono', 30)
        milliseconds = 0
        @anglehour, @anglemin, @anglesec = 0, 0, 0
        @kyowatch = KyoWatchGosu.new
        @kyowatch.total_sec = 0
        @clock = @kyowatch.kyoclock
        @time  = @kyowatch.time_now
        @kyowatch.update_clock
        text = sprintf("%02d:%02d:%02d", @clock[3], @clock[4], @kyowatch.total_sec)
        @text  = text + " #{@clock[5]}"
        @days = [
            ' 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
            ]
    end
   
    def update
        if @kyowatch.total_sec != @sec
            @sec = @kyowatch.total_sec
          @anglesec += 6.0 unless @kyowatch.total_sec == 0
          if @kyowatch.total_sec > 0
              @h_min = sprintf("%02d:%02d:%02d", @time[3], @time[4], @kyowatch.sec)
            @text = @h_min + " #{@kyowatch.time_now[5]}"
          end
        end
        if @kyowatch.time_now.size > 6 and @kyowatch.time_now != @clock
          @anglemin  += 6.0  if @kyowatch.time_now[4] != @time[4]
            hours = @time[3] == nil ? @clock[3] : @time[3]
          @anglehour += 30.0 if @kyowatch.time_now[3] != hours
            @time = @kyowatch.time_now
        end
        @kyowatch.update_clock
    end
   
    def draw
        @clockpic.draw(10, 10, 0)
        @clocksec.draw_rot(110, 110, 2, @anglesec)
        @clockmin.draw_rot(110, 110, 2, @anglemin)
        @clockhour.draw_rot(110, 110, 2, @anglehour)
        @font1.draw(@text, 28, 220, ZOrder::UI, 1.0, 1.0, 0xffffff00)
        draw_day_names
    draw_day_numbers
    end
   
    def draw_day_names
        @names = KyoVocab::KyoDayPartialNames.delete_if{|k,v| k == nil}
        for n in @names.keys
            x = n % 7 * 38
            color = n % 7 == 0 ? 0xffaa0000 : 0xffffffff
            @font2.draw(@names[n], 228+x, 16, ZOrder::UI, 1.0, 1.0, color)
        end
    end
 
    def draw_day_numbers
        days = @days
        @days.pop @days.size-KyoVocab::REGYEAR[4]
        for n in @days
            x = @days.index(n) % 7 * 38
            y = @days.index(n) / 7 * 40
            color = @days.index(n) % 7 == 0 ? 0xffaa0000 : 0xffffffff
          @font3.draw(n, 228+x, 48+y, ZOrder::UI, 1.0, 1.0, color)
        end
    end
   
    def button_down(id)
        close if id == Button::KbEscape
    end
end
 
window = GameWindow.new
window.show
[/rgss]
 
Well, I noticed something while I was trying to implement it in a scene system... OK, to create such group of scenes, I was looking at etheon's FDM which ends right after the title screen shows up...

When I finally made it possible to change from Title screen to the Watch screen Ruby started reporting bugs - segmentation faults... and the worst was that it was never found on the same line... Most of the time the problem is found after redrawing the screen... OK, this happened because I included the calendar on the right side... and it uses an interator for each...

I ran my watch stand-alone script and it runs properly...

It seems like the scenery isn't an option for gosu, yet, unless someone tells me how to avoid that terrible bug I get after including the watch script as a simple, optional scene...

project.rb:130: [BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-10-04 revision 19669) [i486-linux]

Ruby 1.8.7 also shows the same backtrace info after it ran the second scene (the watch) for a few seconds...

Edit...

I found 2 bug reports on gosu website regarding Threads and some other iterators... The bugs were considered of medium level of priority at most...
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top