Not logged inGosu Forums
Forum back to libgosu.org Help Search Register Login
Up Topic Gosu / Extending Gosu / Some Gosu requests
- - By Salazar Date 2015-09-14 19:48
Hi to all!

I'm new here on forum, and just newbie with Gosu (about 2 months). And I'm from Russia and don't realy often use english, so don't blame me to hard for possible mistakes))

So...

I'm in construction of my own engine. I'm using Gosu, Rmagick, Inifile, Chipmunk and Chingu (two lasts I'm not really use by now, maybe later). And in produsing my engine I thought about (IMHO) usefull features? that could be implemented in Gosu, because I use them every time, but don't see them in Gosu...

They are:

1. Method (and also a class) for cursor. By now I'm using somewhat similar to this:

class GameCursor
  attr_accessor :image
  def initialize filename = nil
    case filename
       when nil; Gosu::Window.class_eval {def needs_cursor?; false; end}
       when  "";  Gosu::Window.class_eval {def needs_cursor?; true; end}
       when String
           Gosu::Window.class_eval {def needs_cursor?; false; end}
          @image = Gosu::Image.new(filename)
    end
  end

  def draw x, y; @image.draw(x, y, 100000); end
end

#and in my main class:

class MyClass < Gosu::Window
  def initialize #...
    #...
    @cursor = GameCursor.new (#...)
    #...
  end
#....
  def draw
     @cursor.draw
     #...
   end
end

This is not all, that I do with my cursor object (not only implement custom image for it))), but these are basics, that I thought, should be in Gosu core... (Rubygame has this)

2. Is there any way to draw Magick::Image instead of Gosu::Image? I'm on Windows7, so method #display doesn't fit to me))

3. I'm in need to know screen resolution of user, that will be play my games. For now I'm using Tk methods such are:

require 'tk'

$screen_width  = TkWinfo.screenwidth(Tk.root)
$screen_height = TkWinfo.screenheight(Tk.root)

#and so on... aspect ratio, scale factros, restricted on screew width, that user sets in ini-file...

In last update you began integration with Tk, so I thought, that maybe some of this features could be implemented in gosu core?

That is not all, but for the first time it's ok. I would be grateful for an answer!
Parent - - By jlnr (dev) Date 2015-09-15 21:57
Hi and welcome :)

1. Instead of rewriting methods on Gosu::Window with class_eval, you can just add a setter to your own Window subclass:

class MyWindow < Gosu::Window
  ...
  attr_accessor :cursor
 
  def initialize(...)
    ...
    # Neither default cursor, nor a custom cursor image - I think this makes for nicer code than ""
    @cursor = false
  end

  def needs_cursor?
    @cursor.nil?
  end

  def draw
    ...
    if @cursor then
      # This is a bit of a hack - it's probably better to cache cursors indefinitely in a Hash
      @cursor_image ||= Gosu::Image.new(@cursor)
      @cursor_image.draw mouse_x, mouse_y, 1000000
    end
  end
end


2. No, Magick::Image is a bitmap in memory, Gosu::Image is an OpenGL texture, or something similar. But you can convert RMagick images to Gosu using Gosu::Image.new(rmagick_image).

(And I feel I have to point out that releasing games that depend on RMagick is going to be complicated =/ Deploying Texplay is a lot easier.)

3. Gosu::screen_width and Gosu::screen_height are your friend.

Thanks for the feedback! I'll try to look at the asynchronous image loading soon-ish, as well.
Parent - - By Salazar Date 2015-09-16 08:39 Edited 2015-09-16 08:47
Thanks for answer!

I use only RMagick, because TexPlay doesn't work with Ruby 2.2. And, Rmagick, obviously more functional.
Parent - By jlnr (dev) Date 2015-09-16 09:30
Oh, I didn't know that about TexPlay. =/
- - By Salazar Date 2015-09-18 21:05
And one more question...

I couldn't understand how to privide a mouse double_clicking (( Didn't find this anywhere. Could someone provide me with a sample code of such event?
Parent - - By RunnerPack Date 2015-09-20 00:30
If you think about the problem for a while, I'm sure you could come up with your own solution, but I like to solve little programming challenges like this, so I'll share mine.

Detecting that the mouse is over the item of interest is left as an exercise for the reader ;)
Attachment: GosuRubyDoubleClick.7z - Sample code to detect double-clicks in Ruby (7k)
Parent - - By Salazar Date 2015-09-20 07:24
Yeah! That's work! BTW, after posting this question, I spend some time to do this myself and my code was just as yours, except the minimal range of pointer DBLCLICKDIST)) Thanks for your help!
Parent - - By RunnerPack Date 2015-09-20 15:13
You're quite welcome.
I knew you could do it, but to make it really robust, you need that distance check (which Gosu makes very easy, as you can see). It's been in MS Windows since the beginning for a reason ;)
Parent - - By Salazar Date 2015-09-23 09:59 Edited 2015-09-23 13:12
I went a little bit futher and impliment this feature to Gosu-core:

module Gosu

  MsDoubleLeft  = "Mouse left  button is double-clicked"
  MsDoubleRight = "Mouse right button is double-clicked"

  class Window

    DBLCLICKTIME = 500
    DBLCLICKDIST = 5

    def button_down id
      if id == Gosu::MsLeft
        if @click
          fast_enough  = (Gosu.milliseconds - @time_now < DBLCLICKTIME)
          close_enough = (distance(@now_x, @now_y, mouse_x, mouse_y) <= DBLCLICKDIST)
          @click = false
          fast_enough and close_enough ? MsDoubleLeft : id
        else
          @time_now = Gosu.milliseconds
          @now_x, @now_y = mouse_x, mouse_y
          @click = true
          id
        end
      end
    end
  end
end

Now in my MainWindow < Gosu::Window I use this:

def button_down id
  id = super id
  #...other logic
end

This helps me to capture double-click event with less code)) But have you any ideas how to improve this even more?
Parent - - By RunnerPack Date 2015-09-24 03:26
Great work! I'm not sure how much more functionality a simple double-click test needs, but there is one thing...

While writing my code, I thought a bit about how one would integrate it into Gosu. At first, I assumed a double-click shouldn't trigger either of the constituent single-clicks. However, to do this, you'd have to defer reporting the first click until after the timeout, so you can throw it (and the second click) away if the user completed the double-click. Thinking some more, I decided it wouldn't be worth the trouble to implement, especially considering that wouldn't always be the desired functionality (e.g. when getting single clicks rapidly is the goal, as it often is in mouse-based games). If I'm reading it right, your code throws away the second click, but still triggers the first one immediately. This is probably a good compromise, but still isn't ideal in all cases, and will almost always still have to be worked around, even when you don't care about rapid-fire clicks.

More comments on your code:
1. Why are "MsDoubleLeft" and "...Right" strings? It seems wasteful of memory and CPU cycles. Why not just use symbols like (I think/assume) Gosu does?
2. As jlnr mentioned before, it's better to simply subclass Gosu::Window, rather than "monkey-patching" functionality into it at runtime. If you want to keep your code clean, you can use separate, "require_relative'd" files to break things up for readability.
Parent - By jlnr (dev) Date 2015-09-24 04:56
Gosu's button constants are integers (Fixnums):

https://github.com/gosu/gosu/blob/master/Gosu/Buttons.hpp#L127-L141

It would probably be best to pick two random unused Fixnums for new constants, to avoid collisions.
- - By Salazar Date 2015-10-05 11:55
This is very dumb question may be, but...

Could anyone provide me a small guide to "Game saving"? I didn't find this information anywhere. How can I implement a save|load -game features to my project?
Parent - - By jahmaican Date 2015-10-05 13:09
It is a perfectly valid question and there's definitely more than one valid answer. Also, it has very little to do with the technology you use, and much more with your design choices.

First of all, you have to answer yourself what defines your "game state" - for example it would be variables for level number and user position. Easy approach would be to wrap these variables into a GameState class. Now when your game has a game_state object you can serialize/deserialize it on save/load events - and that's about it.
Parent - - By Salazar Date 2015-10-05 15:18
So, as I see, I'll need to use Marshal module? But how deep can it goes? My GameState consisits of VERY many other classes. Let's think about it like that: GameState is some kind of location. In this location are: my party (class Party) and other NPCs (class NPC). My Party consisit of heroes (class Hero) and every hero has @hp, @mp and so on. Also, every hero has its equipment, wich is instance of Item class, and every item, of course, has its own attributes. Some of them generates on the fly, some could be taken from database file... And every NPC has its own attributes... So? What object should I marshalize?))
Parent - By lol_o2 Date 2015-10-05 17:26
You can marshalize fairly everything. The biggest object I marshaled was whole world (editor data). It was a hash, which consisted of rooms, which had object and objects had attributes. The whole file was over 20MB and loaded few seconds, but it was doing right.
Parent - By jahmaican Date 2015-10-06 06:52
Well, if your game state is complex, then your save file can get complex too. So what do you serialize? Well, that depends on you. You can, as stated above, marshalize almost everything. You can have a state object for every game object that can be altered and iterate through them. You could have a Save class that would be a minimal representation from which you are able to restore game state (good idea when yous savefiles are getting too big, but will require additional coding + it might be tricky to keep it consistent during development).

Also, ask yourself how exactly should the save mechanism work - should I spawn in the exact same position or in the checkpoint? should enemies/exploding barrel respawn? should my health regen? etc., because some of these choices may complicate/simplify your saving mechanics.
- - By Salazar Date 2015-11-05 06:55
I have one more question. Is it possible to draw text with Image.from_text with different colors of words in the same string?
Parent - - By jlnr (dev) Date 2015-11-05 09:07
Yes, try this: "Hello <c=ff00ff>World!</c>"

I'm afraid the syntax is VERY poorly documented, but for now this should do the trick :)
Parent - By Salazar Date 2015-11-05 16:13
Yeah! It works! Thanks!
Up Topic Gosu / Extending Gosu / Some Gosu requests

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill