Snippet - Sin/Cos functions

This will be helpful to some. I make helper functions to estimate sin and cos functions. I used Taylor series to estimate. Here's an example drawing a dot at the position of the crank:

on draw do
	// Draw a crank dot
	if event.ra!=0 then
		a = event.aa
		a /= 180
		a *= 3.14159
		emit "sin"
		emit "cos"
		x = sin
		x *= 32
		x += 32
		x += 2
		
		y = cos
		y *= 32
		y += 32
		y += 2
	end
	fill "white" at x,y,4,4
end

Put this in the game script:


on sin do
	aNorm = a
	while aNorm>=3.141592 do
		aNorm -= 6.283184
	end
	
	n = 0
	modifier = 1
	sin = 0
	while n<6 do
		// modifier * aNorm^(2n+1)
		// -------------------
		// (2n+1)!
		pow = n
		pow *= 2
		pow += 1
		
		// numerator
		num = modifier
		p = pow
		while p>0 do
			num *= aNorm
			p--
		end
		
		// denominator
		f = pow
		den = 1
		while f>0 do
			den *= f
			f--
		end
		if den==0 then
			den = 1
		end
		
		// log "{modifier} * {num}"
		// log "------------------"
		// log "{den}"
		
		// Add to result
		num /= den
		sin += num
		
		// Set up next loop
		modifier *= -1
		n += 1
	end
end

on cos do
	oldA = a
	oldSin = sin
	a += 1.57079
	call "sin"
	cos = sin
	cos *= -1 // Trig is y up, pulp is y down
	a = oldA
	sin = oldSin
end

the n < 6 is the number of iterations, and I've found 6 is good enough for three decimal places.

Edit: There were some issues when the number was > pi, which I fixed by limiting the angle from -pi to pi.

5 Likes

This is great! I have a couple of questions:

How would we change where on the screen the crank dot appears?

Is it possible to use this function to move the player?

How would we change where on the screen the crank dot appears?

The first snippet shows how to position the dot around a point, but doesn't explicitly say it.

on draw do
	// Draw a crank dot
	if event.ra!=0 then
		a = event.aa
		a /= 180
		a *= 3.14159
		emit "sin"
		emit "cos"
		x = sin
		x *= 32 // Scale the radius 32 pixels wide
		x += 32 // Move the center point 32 pixels to the right
		x += 2
		
		y = cos
		y *= 32 // Scale the radius 32 pixels tall
		y += 32 // Move the center 32 pixels down
		y += 2
	end
	fill "white" at x,y,4,4
end
1 Like

Yes, you could do your math to find where the x and y are, then divide each by 8 to convert to tile coordinates. Then use the goto function to send the player there.

x /= 8
x = floor x
y /= 8
y = floor y

goto x,y

Beware it might not be happy with you using the goto function in the draw event, so you might want to do the math in a regular event if this is your intended action.

1 Like

Bit shaky but that works! I'll fiddle around with it as I go, but thanks very much for the help, this may have solved the problem I've been tussling with all day.

Instead of using emit to call these functions I would use tell event.game and call. emit has to ask the game, current room, player, and all 375 tiles in the current room if they handle the emitted event. That’s a lot more overhead than directly tell-ing the single object you already know implements the event handler. (And that overhead is only being compounded by calling it 20 frames per second in the draw event handler. I would move the sin/cos calculations and setting of x,y to the player’s crank event handler.)

1 Like

@BoldBigflank A short followup: I’ve added native sine and cosine functions to PulpScript (plus tangent, radians, and degrees). One thing I noticed is that your pure PulpScript event handler versions are returning inverted values. So when you switch from these (the native versions provide a huge performance boost, PulpScript wasn't built to be especially math-y :sweat_smile:) you’ll want to invert the new return values with *= -1. The additions should be up sometime this week. (I’ll update this comment when the changes go live.)

4 Likes

Thanks, Shaun! Glad we're getting these functions built in.