[noob] Problem with arrays

Hello,

I have a few issue using arrays.

I’m working with rubySDL to make a vertical shooting game. I have a
ship, which had a collection of “fired_missile”.
The level have a collection of critters on screen.

My main loop is :

def main
self.init_lvl
critest = Critters.new(@screen, SCREEN_W,SCREEN_H/2)
@crit<<critest
while(@finished == false)
background = @screen.format.map_rgb(0, 0, 0)
@screen.fill_rect(0,0,@screen.w,@screen.h,background)
self.event_poll
@ship.move
@ship.draw
cur_crit = @crit
cur_crit.each { |c|
c.move
c.draw
self.check_firing©
}
@screen.update_rect(0,0,@screen.w,@screen.h)
end
end

If I understand my code well, for each critters in @crit collection (or
cur_crit to be more accurate), I move the crit, then draw it, and to
finish I call “check_firing” with the critters in parameter.

Here’s the check_firing code :

def check_firing©
critemp = []
if(@ship.firelist.length!=0)
@ship.firelist.each { |f|
if(f.collide_with?©)
else
critemp<<c
end
@crit = critemp
}
end
end

The amusing part is that all work well if I fire only one missile. When
I fire more, it becomes unclear : the critters won’t disappear, and
(surprisingly) it goes faster.

I used the cur_crit temporary array in the main function because
modifying the @crit array while looping on it was kind of hazardous.

If someone have an idea, it will be greatly appreciated :wink:
Thanks.

Ok, my mistake, I was lost in loops :stuck_out_tongue:

So, to explain that simply, I passed c as an argument so it became
persistant outside the @crit.

Sylvain P. wrote:

Hello,

Sylvain P. wrote:

Hello,

I have a few issue using arrays.

I’m working with rubySDL to make a vertical shooting game. I have a
ship, which had a collection of “fired_missile”.
The level have a collection of critters on screen.

I saw your later post that this is working, but I thought that since
you’re a newcomer, I’d just point a few things about your programming
style that aren’t so Rubyish…

My main loop is :

def main
self.init_lvl
critest = Critters.new(@screen, SCREEN_W,SCREEN_H/2)

If each instance of this class represents one critter, then it would
usually best to call the class Critter (in the singular).

@crit<<critest

I think most Rubyists use spaces around operators, for what that’s
worth…

while(@finished == false)

You don’t need the parentheses or the “== false”. You probably just
want “while !@finished”.

Caveat: that will also return true if @finished is nil.

  background = @screen.format.map_rgb(0, 0, 0)
  @screen.fill_rect(0,0,@screen.w,@screen.h,background)
  self.event_poll
  @ship.move
  @ship.draw
  cur_crit = @crit
  cur_crit.each { |c|

In general, “do…end” is used for multiline blocks. The {} syntax is
usually reserved for blocks on a single line. It is very rare to use
{} as you’ve used it here.

  c.move
  c.draw
  self.check_firing(c)
  }
  @screen.update_rect(0,0,@screen.w,@screen.h)

That’s a long loop! Why not put it in a method of its own? You might
also want to put the cur_crit.each block in a method of its own.

end

end

If I understand my code well, for each critters in @crit collection (or
cur_crit to be more accurate), I move the crit, then draw it, and to
finish I call “check_firing” with the critters in parameter.

Here’s the check_firing code :

def check_firing©
critemp = []
if(@ship.firelist.length!=0)

Unnecessary. If the length is 0, then the each in the next line will
simply perform its block 0 times.

Now, if firelist could be nil, then you’ll need to check for that. “if
@ship.firelist” would be sufficient.

  @ship.firelist.each { |f|
    if(f.collide_with?(c))
    else
      critemp<<c
    end

Why do you have an empty if clause? You could make this much more
readable by reversing the conditional (and removing some parentheses):

if !f.collide_with?©
critemp << c
end

    @crit = critemp
  }
end

end

Are you sure about your logic here? The only thing that will be written
to @crit is an array containing multiple copies of c. No further
information, just multiple copies of c.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Luc H. wrote:

On 12 f�vr. 2010, at 18:10, Marnen Laibow-Koser wrote:

You don’t need the parentheses or the “== false”. You probably just
want “while !@finished”.

Even better: until @finished

Thanks! I forgot about until.

if !f.collide_with?©

Same here: unless f.collide_with?©

I don’t like unless. I find it less confusing, in most cases, to write
if !. But it certainly is an option.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Fri, Feb 12, 2010 at 12:03 PM, Luc H. [email protected]
wrote:


Luc H. - [email protected]

I would also define getters for boolean variables

def finished?
!!@finished
end

until finished?

end

I try to restrict direct references to instance variables, and instead
use
them through methods, it seems like better encapsulation to me. For
example,
maybe later I realize I can tell if it is finished by checking something
else rather than storing state in an instance variable, then there is
only
the setter and getter methods that need to be looked at, rather than
every
place I used the instance variable.

I guess I see the method as an interface to the functionality, and the
instance variable as the implementation.

On 12 févr. 2010, at 18:10, Marnen Laibow-Koser wrote:

You don’t need the parentheses or the “== false”. You probably just
want “while !@finished”.

Even better: until @finished

if !f.collide_with?©

Same here: unless f.collide_with?©

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs